Implement drafts, introduce Room persistence library for db #139

Open
mmarif wants to merge 25 commits from 15-comments-draft into master
34 changed files with 2330 additions and 347 deletions

View File

@ -76,6 +76,8 @@ dependencies {
implementation "com.hendraanggrian.appcompat:socialview-commons:0.2"
implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version"
implementation "androidx.lifecycle:lifecycle-viewmodel:$lifecycle_version"
implementation "android.arch.persistence.room:runtime:1.1.1"
annotationProcessor "android.arch.persistence.room:compiler:1.1.1"
implementation "com.github.HamidrezaAmz:BreadcrumbsView:0.2.9"
implementation "commons-io:commons-io:20030203.000550"
implementation "com.github.chrisbanes:PhotoView:2.3.0"
@ -84,5 +86,7 @@ dependencies {
implementation "ch.acra:acra-mail:$acra"
implementation "ch.acra:acra-limiter:$acra"
implementation "ch.acra:acra-notification:$acra"
implementation "androidx.room:room-runtime:2.2.5"
annotationProcessor "androidx.room:room-compiler:2.2.5"
}

View File

@ -20,9 +20,11 @@ import android.widget.Spinner;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.lifecycle.LifecycleOwner;
import com.tooltip.Tooltip;
import org.mian.gitnex.R;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.database.repository.UserAccountsRepository;
import org.mian.gitnex.helpers.NetworkObserver;
import org.mian.gitnex.helpers.SnackBar;
import org.mian.gitnex.helpers.VersionCheck;
@ -31,6 +33,7 @@ import org.mian.gitnex.models.UserInfo;
import org.mian.gitnex.models.UserTokens;
import org.mian.gitnex.util.AppUtil;
import org.mian.gitnex.util.TinyDB;
import org.mian.gitnex.viewmodels.UserAccountsDatabaseViewModel;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.charset.StandardCharsets;
@ -547,6 +550,18 @@ public class LoginActivity extends BaseActivity implements View.OnClickListener
tinyDb.putString("loginUid", userDetails.getLogin());
tinyDb.putString("userLogin", userDetails.getUsername());
// insert new account to db if does not exist
String accountName = userDetails.getUsername() + "@" + instanceUrl;
UserAccountsRepository userAccountsRepository = new UserAccountsRepository(ctx);
UserAccountsDatabaseViewModel.getCount(accountName).observe((LifecycleOwner) ctx, count -> {
if(count == 0) {
userAccountsRepository.insertNewAccount(accountName, instanceUrl, userDetails.getUsername(), loginToken_,"");
}
});
enableProcessButton();
loginButton.setText(R.string.btnLogin);
startActivity(new Intent(LoginActivity.this, MainActivity.class));
@ -711,6 +726,18 @@ public class LoginActivity extends BaseActivity implements View.OnClickListener
tinyDb.putString(loginUid + "-token", newToken.getSha1());
tinyDb.putString(loginUid + "-token-last-eight", appUtil.getLastCharactersOfWord(newToken.getSha1(), 8));
// insert new account to db if does not exist
String accountName = userDetails.getUsername() + "@" + instanceUrl;
UserAccountsRepository userAccountsRepository = new UserAccountsRepository(ctx);
UserAccountsDatabaseViewModel.getCount(accountName).observe((LifecycleOwner) ctx, count -> {
if(count == 0) {
userAccountsRepository.insertNewAccount(accountName, instanceUrl, userDetails.getUsername(), newToken.getSha1(),"");
}
});
startActivity(new Intent(LoginActivity.this, MainActivity.class));
finish();
@ -771,7 +798,8 @@ public class LoginActivity extends BaseActivity implements View.OnClickListener
}
else {
String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
String token = tinyDb.getString(loginUid + "-token");
String instanceToken = "token " + token;
Call<UserInfo> callGetUsername = RetrofitClient
.getInstance(instanceUrl, getApplicationContext())
@ -793,6 +821,19 @@ public class LoginActivity extends BaseActivity implements View.OnClickListener
tinyDb.putString("userLogin", userDetails.getUsername());
tinyDb.putBoolean("loggedInMode", true);
// insert new account to db if does not exist
String accountName = userDetails.getUsername() + "@" + instanceUrl;
UserAccountsRepository userAccountsRepository = new UserAccountsRepository(ctx);
UserAccountsDatabaseViewModel.getCount(accountName).observe((LifecycleOwner) ctx, count -> {
if(count == 0) {
userAccountsRepository.insertNewAccount(accountName, instanceUrl, userDetails.getUsername(), token,"");
}
});
startActivity(new Intent(LoginActivity.this, MainActivity.class));
finish();

View File

@ -16,6 +16,7 @@ import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.appcompat.app.ActionBarDrawerToggle;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.widget.Toolbar;
import androidx.core.view.GravityCompat;
import androidx.drawerlayout.widget.DrawerLayout;
@ -26,7 +27,11 @@ import com.squareup.picasso.NetworkPolicy;
import org.mian.gitnex.R;
import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.database.models.UserAccounts;
import org.mian.gitnex.database.repository.UserAccountsRepository;
import org.mian.gitnex.fragments.AboutFragment;
import org.mian.gitnex.fragments.BottomSheetDraftsFragment;
import org.mian.gitnex.fragments.DraftsFragment;
import org.mian.gitnex.fragments.AdministrationFragment;
import org.mian.gitnex.fragments.ExploreRepositoriesFragment;
import org.mian.gitnex.fragments.MyRepositoriesFragment;
@ -45,6 +50,7 @@ import org.mian.gitnex.models.UserInfo;
import org.mian.gitnex.util.AppUtil;
import org.mian.gitnex.util.TinyDB;
import java.util.Objects;
import java.util.concurrent.ExecutionException;
import retrofit2.Call;
import retrofit2.Callback;
@ -52,372 +58,472 @@ import retrofit2.Callback;
* Author M M Arif
*/
public class MainActivity extends BaseActivity implements NavigationView.OnNavigationItemSelectedListener {
public class MainActivity extends BaseActivity implements NavigationView.OnNavigationItemSelectedListener, BottomSheetDraftsFragment.BottomSheetListener {
private DrawerLayout drawer;
private TextView userFullName;
private TextView userEmail;
private ImageView userAvatar;
private TextView toolbarTitle;
final Context ctx = this;
private Typeface myTypeface;
private DrawerLayout drawer;
private TextView userFullName;
private TextView userEmail;
private ImageView userAvatar;
private TextView toolbarTitle;
final Context ctx = this;
private Typeface myTypeface;
@Override
protected int getLayoutResourceId(){
return R.layout.activity_main;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final TinyDB tinyDb = new TinyDB(getApplicationContext());
tinyDb.putBoolean("noConnection", false);
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
if(tinyDb.getString("dateFormat").isEmpty()) {
tinyDb.putString("dateFormat", "pretty");
}
if(tinyDb.getString("codeBlockStr").isEmpty()) {
tinyDb.putInt("codeBlockColor", getResources().getColor(R.color.colorLightGreen));
tinyDb.putInt("codeBlockBackground", getResources().getColor(R.color.black));
}
if(tinyDb.getString("enableCounterIssueBadgeInit").isEmpty()) {
tinyDb.putBoolean("enableCounterIssueBadge", true);
}
if(tinyDb.getString("homeScreenStr").isEmpty()) {
tinyDb.putInt("homeScreenId", 0);
}
boolean connToInternet = AppUtil.haveNetworkConnection(getApplicationContext());
if(!tinyDb.getBoolean("loggedInMode")) {
logout(this, ctx);
return;
}
String accountName = loginUid + "@" + instanceUrl;
try {
getAcountData(accountName);
}
catch(ExecutionException | InterruptedException e) {
Log.e("getAcountData", e.toString());
}
Toolbar toolbar = findViewById(R.id.toolbar);
toolbarTitle = toolbar.findViewById(R.id.toolbar_title);
switch(tinyDb.getInt("customFontId", -1)) {
case 0:
myTypeface = Typeface.createFromAsset(getAssets(), "fonts/roboto.ttf");
break;
case 2:
myTypeface = Typeface.createFromAsset(getAssets(), "fonts/sourcecodeproregular.ttf");
break;
default:
myTypeface = Typeface.createFromAsset(getAssets(), "fonts/manroperegular.ttf");
break;
}
toolbarTitle.setTypeface(myTypeface);
setSupportActionBar(toolbar);
FragmentManager fm = getSupportFragmentManager();
Fragment fragmentById = fm.findFragmentById(R.id.fragment_container);
if (fragmentById instanceof SettingsFragment) {
toolbarTitle.setText(getResources().getString(R.string.pageTitleSettings));
}
else if (fragmentById instanceof MyRepositoriesFragment) {
toolbarTitle.setText(getResources().getString(R.string.pageTitleMyRepos));
}
else if (fragmentById instanceof StarredRepositoriesFragment) {
toolbarTitle.setText(getResources().getString(R.string.pageTitleStarredRepos));
}
else if (fragmentById instanceof OrganizationsFragment) {
toolbarTitle.setText(getResources().getString(R.string.pageTitleOrganizations));
}
else if (fragmentById instanceof ExploreRepositoriesFragment) {
toolbarTitle.setText(getResources().getString(R.string.pageTitleExplore));
}
else if (fragmentById instanceof ProfileFragment) {
toolbarTitle.setText(getResources().getString(R.string.pageTitleProfile));
}
else if (fragmentById instanceof AboutFragment) {
toolbarTitle.setText(getResources().getString(R.string.pageTitleAbout));
}
else if (fragmentById instanceof DraftsFragment) {
toolbarTitle.setText(getResources().getString(R.string.pageTitleDrafts));
}
else if (fragmentById instanceof AdministrationFragment) {
toolbarTitle.setText(getResources().getString(R.string.pageTitleAdministration));
}
drawer = findViewById(R.id.drawer_layout);
NavigationView navigationView = findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);
final View hView = navigationView.getHeaderView(0);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(this, drawer, toolbar,
R.string.navigation_drawer_open, R.string.navigation_drawer_close);
toggle.getDrawerArrowDrawable().setColor(getResources().getColor(R.color.darkGreen));
drawer.addDrawerListener(toggle);
drawer.addDrawerListener(new DrawerLayout.DrawerListener() {
@Override
public void onDrawerSlide(@NonNull View drawerView, float slideOffset) {
}
@Override
public void onDrawerOpened(@NonNull View drawerView) {
if(tinyDb.getBoolean("noConnection")) {
Toasty.info(getApplicationContext(), getResources().getString(R.string.checkNetConnection));
tinyDb.putBoolean("noConnection", false);
}
String userEmailNav = tinyDb.getString("userEmail");
String userFullNameNav = tinyDb.getString("userFullname");
String userAvatarNav = tinyDb.getString("userAvatar");
userEmail = hView.findViewById(R.id.userEmail);
if (!userEmailNav.equals("")) {
userEmail.setText(userEmailNav);
userEmail.setTypeface(myTypeface);
}
userFullName = hView.findViewById(R.id.userFullname);
if (!userFullNameNav.equals("")) {
userFullName.setText(userFullNameNav);
userFullName.setTypeface(myTypeface);
}
userAvatar = hView.findViewById(R.id.userAvatar);
if (!userAvatarNav.equals("")) {
PicassoService.getInstance(ctx).get().load(userAvatarNav).networkPolicy(NetworkPolicy.OFFLINE).placeholder(R.drawable.loader_animated).transform(new RoundedTransformation(8, 0)).resize(160, 160).centerCrop().into(userAvatar);
}
userAvatar.setOnClickListener(v -> {
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container,
new ProfileFragment()).commit();
drawer.closeDrawers();
});
}
@Override
public void onDrawerClosed(@NonNull View drawerView) {
// Called when a drawer has settled in a completely closed state.
}
@Override
public void onDrawerStateChanged(int newState) {
// Called when the drawer motion state changes. The new state will be one of STATE_IDLE, STATE_DRAGGING or STATE_SETTLING.
}
});
toggle.syncState();
if(savedInstanceState == null) {
if(tinyDb.getInt("homeScreenId") == 0) {
toolbarTitle.setText(getResources().getString(R.string.pageTitleMyRepos));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container,
new MyRepositoriesFragment()).commit();
navigationView.setCheckedItem(R.id.nav_home);
}
else if(tinyDb.getInt("homeScreenId") == 1) {
toolbarTitle.setText(getResources().getString(R.string.pageTitleStarredRepos));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container,
new StarredRepositoriesFragment()).commit();
navigationView.setCheckedItem(R.id.nav_starred_repos);
}
else if(tinyDb.getInt("homeScreenId") == 2) {
toolbarTitle.setText(getResources().getString(R.string.pageTitleOrganizations));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container,
new OrganizationsFragment()).commit();
navigationView.setCheckedItem(R.id.nav_organizations);
}
else if(tinyDb.getInt("homeScreenId") == 3) {
toolbarTitle.setText(getResources().getString(R.string.pageTitleRepositories));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container,
new RepositoriesFragment()).commit();
navigationView.setCheckedItem(R.id.nav_repositories);
}
else if(tinyDb.getInt("homeScreenId") == 4) {
toolbarTitle.setText(getResources().getString(R.string.pageTitleProfile));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container,
new ProfileFragment()).commit();
navigationView.setCheckedItem(R.id.nav_profile);
}
else {
toolbarTitle.setText(getResources().getString(R.string.pageTitleMyRepos));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container,
new MyRepositoriesFragment()).commit();
navigationView.setCheckedItem(R.id.nav_home);
}
}
if(!connToInternet) {
if(!tinyDb.getBoolean("noConnection")) {
Toasty.info(getApplicationContext(), getResources().getString(R.string.checkNetConnection));
}
tinyDb.putBoolean("noConnection", true);
} else {
displayUserInfo(instanceUrl, instanceToken, loginUid);
giteaVersion(instanceUrl);
tinyDb.putBoolean("noConnection", false);
}
// Changelog popup
int versionCode = 0;
try {
PackageInfo packageInfo = getApplicationContext().getPackageManager()
.getPackageInfo(getApplicationContext().getPackageName(), 0);
versionCode = packageInfo.versionCode;
}
catch (PackageManager.NameNotFoundException e) {
Log.e("changelogDialog", Objects.requireNonNull(e.getMessage()));
}
if (versionCode > tinyDb.getInt("versionCode")) {
tinyDb.putInt("versionCode", versionCode);
tinyDb.putBoolean("versionFlag", true);
ChangeLog changelogDialog = new ChangeLog(this);
changelogDialog.showDialog();
}
}
@Override
protected int getLayoutResourceId() {
public void onButtonClicked(String text) {
return R.layout.activity_main;
}
TinyDB tinyDb = new TinyDB(ctx);
int currentActiveAccountId = tinyDb.getInt("currentActiveAccountId");
@Override
public void onCreate(Bundle savedInstanceState) {
if("deleteDrafts".equals(text)) {
super.onCreate(savedInstanceState);
final TinyDB tinyDb = new TinyDB(getApplicationContext());
tinyDb.putBoolean("noConnection", false);
//userAvatar = findViewById(R.id.userAvatar);
if(currentActiveAccountId > 0) {
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
FragmentManager fm = getSupportFragmentManager();
DraftsFragment frag = (DraftsFragment) fm.findFragmentById(R.id.fragment_container);
if(tinyDb.getString("dateFormat").isEmpty()) {
tinyDb.putString("dateFormat", "pretty");
}
if(frag != null) {
if(tinyDb.getString("codeBlockStr").isEmpty()) {
tinyDb.putInt("codeBlockColor", getResources().getColor(R.color.colorLightGreen));
tinyDb.putInt("codeBlockBackground", getResources().getColor(R.color.black));
}
new AlertDialog.Builder(ctx)
.setTitle(R.string.deleteAllDrafts)
.setIcon(R.drawable.ic_delete)
.setCancelable(false)
.setMessage(R.string.deleteAllDraftsDialogMessage)
.setPositiveButton(R.string.menuDeleteText, (dialog, which) -> {
if(tinyDb.getString("enableCounterIssueBadgeInit").isEmpty()) {
tinyDb.putBoolean("enableCounterIssueBadge", true);
}
frag.deleteAllDrafts(currentActiveAccountId);
dialog.dismiss();
if(tinyDb.getString("homeScreenStr").isEmpty()) {
tinyDb.putInt("homeScreenId", 0);
}
})
.setNegativeButton(R.string.cancelButton, (dialog, which) -> dialog.dismiss())
.show();
boolean connToInternet = AppUtil.haveNetworkConnection(getApplicationContext());
if(!tinyDb.getBoolean("loggedInMode")) {
logout(this, ctx);
return;
}
Toolbar toolbar = findViewById(R.id.toolbar);
toolbarTitle = toolbar.findViewById(R.id.toolbar_title);
switch(tinyDb.getInt("customFontId", -1)) {
case 0:
myTypeface = Typeface.createFromAsset(getAssets(), "fonts/roboto.ttf");
break;
case 2:
myTypeface = Typeface.createFromAsset(getAssets(), "fonts/sourcecodeproregular.ttf");
break;
default:
myTypeface = Typeface.createFromAsset(getAssets(), "fonts/manroperegular.ttf");
break;
}
toolbarTitle.setTypeface(myTypeface);
setSupportActionBar(toolbar);
FragmentManager fm = getSupportFragmentManager();
Fragment fragmentById = fm.findFragmentById(R.id.fragment_container);
if(fragmentById instanceof SettingsFragment) {
toolbarTitle.setText(getResources().getString(R.string.pageTitleSettings));
}
else if(fragmentById instanceof MyRepositoriesFragment) {
toolbarTitle.setText(getResources().getString(R.string.pageTitleMyRepos));
}
else if(fragmentById instanceof StarredRepositoriesFragment) {
toolbarTitle.setText(getResources().getString(R.string.pageTitleStarredRepos));
}
else if(fragmentById instanceof OrganizationsFragment) {
toolbarTitle.setText(getResources().getString(R.string.pageTitleOrganizations));
}
else if(fragmentById instanceof ExploreRepositoriesFragment) {
toolbarTitle.setText(getResources().getString(R.string.pageTitleExplore));
}
else if(fragmentById instanceof ProfileFragment) {
toolbarTitle.setText(getResources().getString(R.string.pageTitleProfile));
}
else if(fragmentById instanceof AboutFragment) {
toolbarTitle.setText(getResources().getString(R.string.pageTitleAbout));
}
else if(fragmentById instanceof AdministrationFragment) {
toolbarTitle.setText(getResources().getString(R.string.pageTitleAdministration));
}
drawer = findViewById(R.id.drawer_layout);
NavigationView navigationView = findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);
final View hView = navigationView.getHeaderView(0);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
toggle.getDrawerArrowDrawable().setColor(getResources().getColor(R.color.darkGreen));
drawer.addDrawerListener(toggle);
drawer.addDrawerListener(new DrawerLayout.DrawerListener() {
@Override
public void onDrawerSlide(@NonNull View drawerView, float slideOffset) {
}
@Override
public void onDrawerOpened(@NonNull View drawerView) {
if(tinyDb.getBoolean("noConnection")) {
Toasty.info(getApplicationContext(), getResources().getString(R.string.checkNetConnection));
tinyDb.putBoolean("noConnection", false);
}
else {
Toasty.error(ctx, getResources().getString(R.string.genericError));
}
String userEmailNav = tinyDb.getString("userEmail");
String userFullNameNav = tinyDb.getString("userFullname");
String userAvatarNav = tinyDb.getString("userAvatar");
userEmail = hView.findViewById(R.id.userEmail);
if(!userEmailNav.equals("")) {
userEmail.setText(userEmailNav);
userEmail.setTypeface(myTypeface);
}
userFullName = hView.findViewById(R.id.userFullname);
if(!userFullNameNav.equals("")) {
userFullName.setText(userFullNameNav);
userFullName.setTypeface(myTypeface);
}
userAvatar = hView.findViewById(R.id.userAvatar);
if(!userAvatarNav.equals("")) {
PicassoService.getInstance(ctx).get().load(userAvatarNav).networkPolicy(NetworkPolicy.OFFLINE).placeholder(R.drawable.loader_animated).transform(new RoundedTransformation(8, 0)).resize(160, 160).centerCrop().into(userAvatar);
}
userAvatar.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new ProfileFragment()).commit();
drawer.closeDrawers();
}
});
}
@Override
public void onDrawerClosed(@NonNull View drawerView) {
// Called when a drawer has settled in a completely closed state.
}
@Override
public void onDrawerStateChanged(int newState) {
// Called when the drawer motion state changes. The new state will be one of STATE_IDLE, STATE_DRAGGING or STATE_SETTLING.
}
});
toggle.syncState();
if(savedInstanceState == null) {
if(tinyDb.getInt("homeScreenId") == 0) {
toolbarTitle.setText(getResources().getString(R.string.pageTitleMyRepos));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new MyRepositoriesFragment()).commit();
navigationView.setCheckedItem(R.id.nav_home);
}
else if(tinyDb.getInt("homeScreenId") == 1) {
toolbarTitle.setText(getResources().getString(R.string.pageTitleStarredRepos));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new StarredRepositoriesFragment()).commit();
navigationView.setCheckedItem(R.id.nav_starred_repos);
}
else if(tinyDb.getInt("homeScreenId") == 2) {
toolbarTitle.setText(getResources().getString(R.string.pageTitleOrganizations));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new OrganizationsFragment()).commit();
navigationView.setCheckedItem(R.id.nav_organizations);
}
else if(tinyDb.getInt("homeScreenId") == 3) {
toolbarTitle.setText(getResources().getString(R.string.pageTitleRepositories));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new RepositoriesFragment()).commit();
navigationView.setCheckedItem(R.id.nav_repositories);
}
else if(tinyDb.getInt("homeScreenId") == 4) {
toolbarTitle.setText(getResources().getString(R.string.pageTitleProfile));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new ProfileFragment()).commit();
navigationView.setCheckedItem(R.id.nav_profile);
}
else {
toolbarTitle.setText(getResources().getString(R.string.pageTitleMyRepos));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new MyRepositoriesFragment()).commit();
navigationView.setCheckedItem(R.id.nav_home);
}
}
if(!connToInternet) {
if(!tinyDb.getBoolean("noConnection")) {
Toasty.info(getApplicationContext(), getResources().getString(R.string.checkNetConnection));
Toasty.error(ctx, getResources().getString(R.string.genericError));
}
tinyDb.putBoolean("noConnection", true);
}
else {
displayUserInfo(instanceUrl, instanceToken, loginUid);
giteaVersion(instanceUrl);
tinyDb.putBoolean("noConnection", false);
}
// Changelog popup
int versionCode = 0;
try {
PackageInfo packageInfo = getApplicationContext().getPackageManager().getPackageInfo(getApplicationContext().getPackageName(), 0);
versionCode = packageInfo.versionCode;
}
catch(PackageManager.NameNotFoundException e) {
Log.e("changelogDialog", Objects.requireNonNull(e.getMessage()));
}
if(versionCode > tinyDb.getInt("versionCode")) {
tinyDb.putInt("versionCode", versionCode);
tinyDb.putBoolean("versionFlag", true);
ChangeLog changelogDialog = new ChangeLog(this);
changelogDialog.showDialog();
}
}
public void setActionBarTitle(@NonNull String title) {
public void getAcountData(String accountName) throws ExecutionException, InterruptedException {
Objects.requireNonNull(getSupportActionBar()).setTitle(title);
}
UserAccountsRepository accountData = new UserAccountsRepository(ctx);
UserAccounts data = accountData.getAccountData(accountName);
if(data != null) {
TinyDB tinyDb = new TinyDB(ctx.getApplicationContext());
tinyDb.putInt("currentActiveAccountId", data.getAccountId());
}
else {
AlertDialogs.forceLogoutDialog(ctx, getResources().getString(R.string.forceLogoutDialogHeader), getResources().getString(R.string.forceLogoutDialogDescription), getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
}
}
@Override
public void onBackPressed() {
public void onBackPressed() {
if(drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
}
else {
super.onBackPressed();
}
if(drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
}
else {
super.onBackPressed();
}
}
}
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem menuItem) {
switch (menuItem.getItemId()) {
case R.id.nav_home:
toolbarTitle.setText(getResources().getString(R.string.pageTitleMyRepos));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container,
new MyRepositoriesFragment()).commit();
break;
case R.id.nav_organizations:
toolbarTitle.setText(getResources().getString(R.string.pageTitleOrganizations));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container,
new OrganizationsFragment()).commit();
break;
case R.id.nav_profile:
toolbarTitle.setText(getResources().getString(R.string.pageTitleProfile));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container,
new ProfileFragment()).commit();
break;
case R.id.nav_repositories:
toolbarTitle.setText(getResources().getString(R.string.pageTitleRepositories));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container,
new RepositoriesFragment()).commit();
break;
case R.id.nav_settings:
toolbarTitle.setText(getResources().getString(R.string.pageTitleSettings));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container,
new SettingsFragment()).commit();
break;
case R.id.nav_logout:
logout(this, ctx);
overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out);
break;
case R.id.nav_about:
toolbarTitle.setText(getResources().getString(R.string.pageTitleAbout));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container,
new AboutFragment()).commit();
break;
case R.id.nav_rate_app:
rateThisApp();
break;
case R.id.nav_starred_repos:
toolbarTitle.setText(getResources().getString(R.string.pageTitleStarredRepos));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container,
new StarredRepositoriesFragment()).commit();
break;
case R.id.nav_explore:
toolbarTitle.setText(getResources().getString(R.string.pageTitleExplore));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container,
new ExploreRepositoriesFragment()).commit();
break;
case R.id.nav_comments_draft:
toolbarTitle.setText(getResources().getString(R.string.pageTitleDrafts));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container,
new DraftsFragment()).commit();
break;
case R.id.nav_administration:
toolbarTitle.setText(getResources().getString(R.string.pageTitleAdministration));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container,
new AdministrationFragment()).commit();
break;
}
drawer.closeDrawer(GravityCompat.START);
return true;
}
public void rateThisApp() {
try {
startActivity(new Intent(Intent.ACTION_VIEW,
Uri.parse("market://details?id=" + getPackageName())));
} catch (ActivityNotFoundException e) {
startActivity(new Intent(Intent.ACTION_VIEW,
Uri.parse("https://play.google.com/store/apps/details?id=" + getPackageName())));
}
}
public static void logout(Activity activity, Context ctx) {
TinyDB tinyDb = new TinyDB(ctx.getApplicationContext());
tinyDb.putBoolean("loggedInMode", false);
tinyDb.remove("basicAuthPassword");
tinyDb.putBoolean("basicAuthFlag", false);
//tinyDb.clear();
activity.finish();
ctx.startActivity(new Intent(ctx, LoginActivity.class));
}
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem menuItem) {
public boolean onOptionsItemSelected(MenuItem item) {
switch(menuItem.getItemId()) {
case R.id.nav_home:
toolbarTitle.setText(getResources().getString(R.string.pageTitleMyRepos));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new MyRepositoriesFragment()).commit();
break;
case R.id.nav_organizations:
toolbarTitle.setText(getResources().getString(R.string.pageTitleOrganizations));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new OrganizationsFragment()).commit();
break;
case R.id.nav_profile:
toolbarTitle.setText(getResources().getString(R.string.pageTitleProfile));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new ProfileFragment()).commit();
break;
case R.id.nav_repositories:
toolbarTitle.setText(getResources().getString(R.string.pageTitleRepositories));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new RepositoriesFragment()).commit();
break;
case R.id.nav_settings:
toolbarTitle.setText(getResources().getString(R.string.pageTitleSettings));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new SettingsFragment()).commit();
break;
case R.id.nav_logout:
logout(this, ctx);
overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out);
break;
case R.id.nav_about:
toolbarTitle.setText(getResources().getString(R.string.pageTitleAbout));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new AboutFragment()).commit();
break;
case R.id.nav_rate_app:
rateThisApp();
break;
case R.id.nav_starred_repos:
toolbarTitle.setText(getResources().getString(R.string.pageTitleStarredRepos));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new StarredRepositoriesFragment()).commit();
break;
case R.id.nav_explore:
toolbarTitle.setText(getResources().getString(R.string.pageTitleExplore));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new ExploreRepositoriesFragment()).commit();
break;
case R.id.nav_administration:
toolbarTitle.setText(getResources().getString(R.string.pageTitleAdministration));
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new AdministrationFragment()).commit();
break;
int id = item.getItemId();
if(id == R.id.genericMenu) {
BottomSheetDraftsFragment bottomSheet = new BottomSheetDraftsFragment();
bottomSheet.show(getSupportFragmentManager(), "draftsBottomSheet");
return true;
}
drawer.closeDrawer(GravityCompat.START);
return true;
}
public void rateThisApp() {
try {
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=" + getPackageName())));
}
catch(ActivityNotFoundException e) {
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("https://play.google.com/store/apps/details?id=" + getPackageName())));
}
}
public static void logout(Activity activity, Context ctx) {
TinyDB tinyDb = new TinyDB(ctx.getApplicationContext());
tinyDb.putBoolean("loggedInMode", false);
tinyDb.remove("basicAuthPassword");
tinyDb.putBoolean("basicAuthFlag", false);
//tinyDb.clear();
activity.finish();
ctx.startActivity(new Intent(ctx, LoginActivity.class));
return super.onOptionsItemSelected(item);
}
private void giteaVersion(final String instanceUrl) {
private void giteaVersion(final String instanceUrl) {
final TinyDB tinyDb = new TinyDB(getApplicationContext());
final TinyDB tinyDb = new TinyDB(getApplicationContext());
final String token = "token " + tinyDb.getString(tinyDb.getString("loginUid") + "-token");
final String token = "token " + tinyDb.getString(tinyDb.getString("loginUid") + "-token");
Call<GiteaVersion> callVersion = RetrofitClient.getInstance(instanceUrl, getApplicationContext()).getApiInterface().getGiteaVersionWithToken(token);
Call<GiteaVersion> callVersion = RetrofitClient
.getInstance(instanceUrl, getApplicationContext())
.getApiInterface()
.getGiteaVersionWithToken(token);
callVersion.enqueue(new Callback<GiteaVersion>() {
callVersion.enqueue(new Callback<GiteaVersion>() {
@Override
public void onResponse(@NonNull final Call<GiteaVersion> callVersion, @NonNull retrofit2.Response<GiteaVersion> responseVersion) {
@Override
public void onResponse(@NonNull final Call<GiteaVersion> callVersion, @NonNull retrofit2.Response<GiteaVersion> responseVersion) {
if(responseVersion.code() == 200) {
if (responseVersion.code() == 200) {
GiteaVersion version = responseVersion.body();
assert version != null;
GiteaVersion version = responseVersion.body();
assert version != null;
tinyDb.putString("giteaVersion", version.getVersion());
tinyDb.putString("giteaVersion", version.getVersion());
}
}
}
}
@Override
public void onFailure(@NonNull Call<GiteaVersion> callVersion, @NonNull Throwable t) {
@Override
public void onFailure(@NonNull Call<GiteaVersion> callVersion, @NonNull Throwable t) {
Log.e("onFailure-version", t.toString());
Log.e("onFailure-version", t.toString());
}
}
});
});
}
}
private void displayUserInfo(String instanceUrl, String token, String loginUid) {
@ -489,13 +595,11 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
userEmail.setText("...");
}
userAvatar.setOnClickListener(new View.OnClickListener() {
userAvatar.setOnClickListener(v -> {
public void onClick(View v) {
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new ProfileFragment()).commit();
drawer.closeDrawers();
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new ProfileFragment()).commit();
drawer.closeDrawers();
}
});
}
@ -508,7 +612,7 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
}
else {
String toastError = getResources().getString(R.string.genericApiStatusError) + String.valueOf(response.code());
String toastError = getResources().getString(R.string.genericApiStatusError) + response.code();
Toasty.info(getApplicationContext(), toastError);
}

View File

@ -7,6 +7,8 @@ import retrofit2.Response;
import android.content.Context;
import android.graphics.drawable.GradientDrawable;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
@ -20,14 +22,17 @@ import com.hendraanggrian.appcompat.widget.SocialAutoCompleteTextView;
import org.mian.gitnex.R;
import org.mian.gitnex.actions.IssueActions;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.database.repository.DraftsRepository;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.StaticGlobalVariables;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.Collaborators;
import org.mian.gitnex.models.Issues;
import org.mian.gitnex.util.AppUtil;
import org.mian.gitnex.util.TinyDB;
import java.util.List;
import java.util.concurrent.ExecutionException;
/**
* Author M M Arif
@ -43,6 +48,7 @@ public class ReplyToIssueActivity extends BaseActivity {
private SocialAutoCompleteTextView addComment;
private ArrayAdapter<Mention> defaultMentionAdapter;
private Button replyButton;
private String TAG = StaticGlobalVariables.replyToIssueActivity;
@Override
protected int getLayoutResourceId(){
@ -83,26 +89,68 @@ public class ReplyToIssueActivity extends BaseActivity {
replyButton = findViewById(R.id.replyButton);
if(getIntent().getStringExtra("commentAction") != null && getIntent().getStringExtra("commentAction").equals("edit")) {
if(getIntent().getStringExtra("commentBody") != null) {
addComment.setText(getIntent().getStringExtra("commentBody"));
}
if(getIntent().getStringExtra("draftTitle") != null) {
toolbar_title.setText(getIntent().getStringExtra("draftTitle"));
}
if(getIntent().getStringExtra("commentAction") != null && getIntent().getStringExtra("commentAction").equals("edit")) {
final String commentId = getIntent().getStringExtra("commentId");
toolbar_title.setText(getResources().getString(R.string.editCommentTitle));
replyButton.setText(getResources().getString(R.string.editCommentButtonText));
replyButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
disableProcessButton();
IssueActions.editIssueComment(ctx, Integer.valueOf(commentId), addComment.getText().toString());
addComment.addTextChangedListener(new TextWatcher() {
public void afterTextChanged(Editable s) {
}
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
public void onTextChanged(CharSequence s, int start, int before, int count) {
saveDraft(addComment.getText().toString());
}
});
replyButton.setOnClickListener(v -> {
disableProcessButton();
IssueActions.editIssueComment(ctx, Integer.parseInt(commentId), addComment.getText().toString());
});
return;
}
addComment.addTextChangedListener(new TextWatcher() {
public void afterTextChanged(Editable s) {
}
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
public void onTextChanged(CharSequence s, int start, int before, int count) {
saveDraft(addComment.getText().toString());
}
});
if(!connToInternet) {
disableProcessButton();
@ -115,6 +163,34 @@ public class ReplyToIssueActivity extends BaseActivity {
}
private void saveDraft(String draftText) {
TinyDB tinyDb = new TinyDB(getApplicationContext());
int repositoryId = (int) tinyDb.getLong("repositoryId", 0);
int currentActiveAccountId = tinyDb.getInt("currentActiveAccountId");
int issueNumber = Integer.parseInt(tinyDb.getString("issueNumber"));
DraftsRepository draftsRepository = new DraftsRepository(getApplicationContext());
try {
int countDraft = draftsRepository.checkDraft(issueNumber, repositoryId);
if(countDraft == 0) {
long draftId = draftsRepository.insertDraft(repositoryId, currentActiveAccountId, issueNumber, draftText, StaticGlobalVariables.draftTypeComment);
}
else {
DraftsRepository.updateDraftByIssueIdAsycTask(draftText, issueNumber, repositoryId);
}
}
catch(ExecutionException | InterruptedException e) {
Log.e(TAG, e.toString());
}
}
public void loadCollaboratorsList() {
final TinyDB tinyDb = new TinyDB(getApplicationContext());
@ -151,7 +227,7 @@ public class ReplyToIssueActivity extends BaseActivity {
} else {
Log.i("onResponse", String.valueOf(response.code()));
Log.i(TAG, String.valueOf(response.code()));
}
@ -159,7 +235,7 @@ public class ReplyToIssueActivity extends BaseActivity {
@Override
public void onFailure(@NonNull Call<List<Collaborators>> call, @NonNull Throwable t) {
Log.i("onFailure", t.getMessage());
Log.e(TAG, t.toString());
}
});
@ -182,6 +258,8 @@ public class ReplyToIssueActivity extends BaseActivity {
private void processNewCommentReply() {
final TinyDB tinyDb = new TinyDB(getApplicationContext());
String newReplyDT = addComment.getText().toString();
boolean connToInternet = AppUtil.haveNetworkConnection(getApplicationContext());
@ -260,7 +338,7 @@ public class ReplyToIssueActivity extends BaseActivity {
@Override
public void onFailure(@NonNull Call<Issues> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
Log.e(TAG, t.toString());
enableProcessButton();
}
});

View File

@ -0,0 +1,127 @@
package org.mian.gitnex.adapters;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import org.mian.gitnex.R;
import org.mian.gitnex.activities.ReplyToIssueActivity;
import org.mian.gitnex.database.models.DraftsWithRepositories;
import org.mian.gitnex.database.repository.DraftsRepository;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.util.TinyDB;
import java.util.List;
/**
* Author M M Arif
*/
public class DraftsAdapter extends RecyclerView.Adapter<DraftsAdapter.DraftsViewHolder> {
private List<DraftsWithRepositories> draftsList;
private Context mCtx;
class DraftsViewHolder extends RecyclerView.ViewHolder {
private TextView draftText;
private TextView repoInfo;
private TextView repoId;
private TextView draftId;
private TextView issueNumber;
private TextView issueType;
private TextView repoOwner;
private TextView repoName;
private DraftsViewHolder(View itemView) {
super(itemView);
draftText = itemView.findViewById(R.id.draftText);
repoInfo = itemView.findViewById(R.id.repoInfo);
repoId = itemView.findViewById(R.id.repoId);
draftId = itemView.findViewById(R.id.draftId);
issueNumber = itemView.findViewById(R.id.issueNumber);
issueType = itemView.findViewById(R.id.issueType);
repoOwner = itemView.findViewById(R.id.repoOwner);
repoName = itemView.findViewById(R.id.repoName);
ImageView deleteDraft = itemView.findViewById(R.id.deleteDraft);
deleteDraft.setOnClickListener(itemDelete -> {
int getDraftId = Integer.parseInt(draftId.getText().toString());
deleteDraft(getAdapterPosition());
DraftsRepository.deleteSingleDraft(getDraftId);
});
draftText.setOnClickListener(itemEdit -> {
Intent intent = new Intent(mCtx, ReplyToIssueActivity.class);
intent.putExtra("commentBody", draftText.getText());
intent.putExtra("issueNumber", issueNumber.getText());
intent.putExtra("repositoryId", repoId.getText());
intent.putExtra("draftTitle", repoInfo.getText());
TinyDB tinyDb = new TinyDB(mCtx);
tinyDb.putString("issueNumber", issueNumber.getText().toString());
tinyDb.putLong("repositoryId", Long.parseLong(repoId.getText().toString()));
//tinyDb.putString("issueType", issueType.getText().toString());
mCtx.startActivity(intent);
});
}
}
public DraftsAdapter(Context mCtx, List<DraftsWithRepositories> draftsListMain) {
this.mCtx = mCtx;
this.draftsList = draftsListMain;
}
private void deleteDraft(int position) {
draftsList.remove(position);
notifyItemRemoved(position);
notifyItemRangeChanged(position, draftsList.size());
Toasty.info(mCtx, mCtx.getResources().getString(R.string.draftsSingleDeleteSuccess));
}
@NonNull
@Override
public DraftsAdapter.DraftsViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_drafts, parent, false);
return new DraftsViewHolder(v);
}
@SuppressLint("DefaultLocale")
@Override
public void onBindViewHolder(@NonNull DraftsAdapter.DraftsViewHolder holder, int position) {
DraftsWithRepositories currentItem = draftsList.get(position);
holder.repoId.setText(String.valueOf(currentItem.getRepositoryId()));
holder.draftId.setText(String.valueOf(currentItem.getDraftId()));
holder.issueNumber.setText(String.valueOf(currentItem.getIssueId()));
holder.issueType.setText(currentItem.getDraftType());
holder.repoOwner.setText(currentItem.getRepositoryOwner());
holder.repoName.setText(currentItem.getRepositoryName());
holder.draftText.setText(currentItem.getDraftText());
holder.repoInfo.setText(String.format("%s/%s %s%d", currentItem.getRepositoryOwner(), currentItem.getRepositoryName(), mCtx.getResources().getString(R.string.hash), currentItem.getIssueId()));
}
@Override
public int getItemCount() {
return draftsList.size();
}
}

View File

@ -4,6 +4,7 @@ import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.graphics.Typeface;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@ -22,12 +23,15 @@ import org.mian.gitnex.activities.RepoStargazersActivity;
import org.mian.gitnex.activities.RepoWatchersActivity;
import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.database.models.Repositories;
import org.mian.gitnex.database.repository.RepositoriesRepository;
import org.mian.gitnex.helpers.RoundedTransformation;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.UserRepositories;
import org.mian.gitnex.models.WatchRepository;
import org.mian.gitnex.util.TinyDB;
import java.util.List;
import java.util.concurrent.ExecutionException;
import retrofit2.Call;
import retrofit2.Callback;
@ -87,12 +91,40 @@ public class ExploreRepositoriesAdapter extends RecyclerView.Adapter<ExploreRepo
tinyDb.putBoolean("resumeIssues", true);
tinyDb.putBoolean("isRepoAdmin", isRepoAdmin.isChecked());
String[] parts = fullName.getText().toString().split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
int currentActiveAccountId = tinyDb.getInt("currentActiveAccountId");
RepositoriesRepository repositoryData = new RepositoriesRepository(context);
try {
//RepositoriesRepository.deleteRepositoriesByAccount(currentActiveAccountId);
Integer count = repositoryData.checkRepository(currentActiveAccountId, repoOwner, repoName);
if(count == 0) {
long id = repositoryData.insertRepository(currentActiveAccountId, repoOwner, repoName);
tinyDb.putLong("repositoryId", id);
}
else {
Repositories data = repositoryData.getRepository(currentActiveAccountId, repoOwner, repoName);
tinyDb.putLong("repositoryId", data.getRepositoryId());
}
}
catch(ExecutionException | InterruptedException e) {
Log.e("checkRepository", e.toString());
}
//store if user is watching this repo
{
final String instanceUrl = tinyDb.getString("instanceUrl");
String[] parts = repoFullName.getText().toString().split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
final String token = "token " + tinyDb.getString(tinyDb.getString("loginUid") + "-token");
WatchRepository watch = new WatchRepository();
@ -133,6 +165,7 @@ public class ExploreRepositoriesAdapter extends RecyclerView.Adapter<ExploreRepo
}
});
}
context.startActivity(intent);

View File

@ -4,6 +4,7 @@ import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.graphics.Typeface;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@ -21,6 +22,8 @@ import org.mian.gitnex.activities.RepoStargazersActivity;
import org.mian.gitnex.activities.RepoWatchersActivity;
import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.database.models.Repositories;
import org.mian.gitnex.database.repository.RepositoriesRepository;
import org.mian.gitnex.helpers.RoundedTransformation;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.UserRepositories;
@ -28,6 +31,7 @@ import org.mian.gitnex.models.WatchRepository;
import org.mian.gitnex.util.TinyDB;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import retrofit2.Call;
@ -56,7 +60,9 @@ public class MyReposListAdapter extends RecyclerView.Adapter<MyReposListAdapter.
private TextView repoType;
private MyReposViewHolder(View itemView) {
super(itemView);
mTextView1My = itemView.findViewById(R.id.repoNameMy);
mTextView2My = itemView.findViewById(R.id.repoDescriptionMy);
imageMy = itemView.findViewById(R.id.imageAvatarMy);
@ -80,12 +86,40 @@ public class MyReposListAdapter extends RecyclerView.Adapter<MyReposListAdapter.
tinyDb.putString("repoType", repoType.getText().toString());
//tinyDb.putBoolean("resumeIssues", true);
String[] parts = fullNameMy.getText().toString().split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
int currentActiveAccountId = tinyDb.getInt("currentActiveAccountId");
RepositoriesRepository repositoryData = new RepositoriesRepository(context);
try {
//RepositoriesRepository.deleteRepositoriesByAccount(currentActiveAccountId);
Integer count = repositoryData.checkRepository(currentActiveAccountId, repoOwner, repoName);
if(count == 0) {
long id = repositoryData.insertRepository(currentActiveAccountId, repoOwner, repoName);
tinyDb.putLong("repositoryId", id);
}
else {
Repositories data = repositoryData.getRepository(currentActiveAccountId, repoOwner, repoName);
tinyDb.putLong("repositoryId", data.getRepositoryId());
}
}
catch(ExecutionException | InterruptedException e) {
Log.e("checkRepository", e.toString());
}
//store if user is watching this repo
{
final String instanceUrl = tinyDb.getString("instanceUrl");
String[] parts = fullNameMy.getText().toString().split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
final String token = "token " + tinyDb.getString(tinyDb.getString("loginUid") + "-token");
WatchRepository watch = new WatchRepository();
@ -126,6 +160,7 @@ public class MyReposListAdapter extends RecyclerView.Adapter<MyReposListAdapter.
}
});
}
context.startActivity(intent);

View File

@ -4,6 +4,7 @@ import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.graphics.Typeface;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@ -24,6 +25,8 @@ import org.mian.gitnex.activities.RepoStargazersActivity;
import org.mian.gitnex.activities.RepoWatchersActivity;
import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.database.models.Repositories;
import org.mian.gitnex.database.repository.RepositoriesRepository;
import org.mian.gitnex.helpers.RoundedTransformation;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.UserRepositories;
@ -31,6 +34,7 @@ import org.mian.gitnex.models.WatchRepository;
import org.mian.gitnex.util.TinyDB;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import retrofit2.Call;
import retrofit2.Callback;
@ -87,12 +91,40 @@ public class ReposListAdapter extends RecyclerView.Adapter<ReposListAdapter.Repo
//tinyDb.putBoolean("resumeIssues", true);
tinyDb.putBoolean("isRepoAdmin", isRepoAdmin.isChecked());
String[] parts = repoFullName.getText().toString().split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
int currentActiveAccountId = tinyDb.getInt("currentActiveAccountId");
RepositoriesRepository repositoryData = new RepositoriesRepository(context);
try {
//RepositoriesRepository.deleteRepositoriesByAccount(currentActiveAccountId);
Integer count = repositoryData.checkRepository(currentActiveAccountId, repoOwner, repoName);
if(count == 0) {
long id = repositoryData.insertRepository(currentActiveAccountId, repoOwner, repoName);
tinyDb.putLong("repositoryId", id);
}
else {
Repositories data = repositoryData.getRepository(currentActiveAccountId, repoOwner, repoName);
tinyDb.putLong("repositoryId", data.getRepositoryId());
}
}
catch(ExecutionException | InterruptedException e) {
Log.e("checkRepository", e.toString());
}
//store if user is watching this repo
{
final String instanceUrl = tinyDb.getString("instanceUrl");
String[] parts = repoFullName.getText().toString().split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
final String token = "token " + tinyDb.getString(tinyDb.getString("loginUid") + "-token");
WatchRepository watch = new WatchRepository();
@ -133,6 +165,7 @@ public class ReposListAdapter extends RecyclerView.Adapter<ReposListAdapter.Repo
}
});
}
context.startActivity(intent);

View File

@ -4,6 +4,7 @@ import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.graphics.Typeface;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@ -22,6 +23,8 @@ import org.mian.gitnex.activities.RepoStargazersActivity;
import org.mian.gitnex.activities.RepoWatchersActivity;
import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.database.models.Repositories;
import org.mian.gitnex.database.repository.RepositoriesRepository;
import org.mian.gitnex.helpers.RoundedTransformation;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.UserRepositories;
@ -29,6 +32,7 @@ import org.mian.gitnex.models.WatchRepository;
import org.mian.gitnex.util.TinyDB;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import retrofit2.Call;
@ -84,12 +88,40 @@ public class RepositoriesByOrgAdapter extends RecyclerView.Adapter<RepositoriesB
//tinyDb.putBoolean("resumeIssues", true);
tinyDb.putBoolean("isRepoAdmin", isRepoAdmin.isChecked());
String[] parts = fullName.getText().toString().split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
int currentActiveAccountId = tinyDb.getInt("currentActiveAccountId");
RepositoriesRepository repositoryData = new RepositoriesRepository(context);
try {
//RepositoriesRepository.deleteRepositoriesByAccount(currentActiveAccountId);
Integer count = repositoryData.checkRepository(currentActiveAccountId, repoOwner, repoName);
if(count == 0) {
long id = repositoryData.insertRepository(currentActiveAccountId, repoOwner, repoName);
tinyDb.putLong("repositoryId", id);
}
else {
Repositories data = repositoryData.getRepository(currentActiveAccountId, repoOwner, repoName);
tinyDb.putLong("repositoryId", data.getRepositoryId());
}
}
catch(ExecutionException | InterruptedException e) {
Log.e("checkRepository", e.toString());
}
//store if user is watching this repo
{
final String instanceUrl = tinyDb.getString("instanceUrl");
String[] parts = fullName.getText().toString().split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
final String token = "token " + tinyDb.getString(tinyDb.getString("loginUid") + "-token");
WatchRepository watch = new WatchRepository();
@ -130,6 +162,7 @@ public class RepositoriesByOrgAdapter extends RecyclerView.Adapter<RepositoriesB
}
});
}
context.startActivity(intent);

View File

@ -4,6 +4,7 @@ import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.graphics.Typeface;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@ -22,6 +23,8 @@ import org.mian.gitnex.activities.RepoStargazersActivity;
import org.mian.gitnex.activities.RepoWatchersActivity;
import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.database.models.Repositories;
import org.mian.gitnex.database.repository.RepositoriesRepository;
import org.mian.gitnex.helpers.RoundedTransformation;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.UserRepositories;
@ -29,6 +32,7 @@ import org.mian.gitnex.models.WatchRepository;
import org.mian.gitnex.util.TinyDB;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import retrofit2.Call;
@ -84,12 +88,40 @@ public class StarredReposListAdapter extends RecyclerView.Adapter<StarredReposLi
//tinyDb.putBoolean("resumeIssues", true);
tinyDb.putBoolean("isRepoAdmin", isRepoAdmin.isChecked());
String[] parts = fullName.getText().toString().split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
int currentActiveAccountId = tinyDb.getInt("currentActiveAccountId");
RepositoriesRepository repositoryData = new RepositoriesRepository(context);
try {
//RepositoriesRepository.deleteRepositoriesByAccount(currentActiveAccountId);
Integer count = repositoryData.checkRepository(currentActiveAccountId, repoOwner, repoName);
if(count == 0) {
long id = repositoryData.insertRepository(currentActiveAccountId, repoOwner, repoName);
tinyDb.putLong("repositoryId", id);
}
else {
Repositories data = repositoryData.getRepository(currentActiveAccountId, repoOwner, repoName);
tinyDb.putLong("repositoryId", data.getRepositoryId());
}
}
catch(ExecutionException | InterruptedException e) {
Log.e("checkRepository", e.toString());
}
//store if user is watching this repo
{
final String instanceUrl = tinyDb.getString("instanceUrl");
String[] parts = fullName.getText().toString().split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];
final String token = "token " + tinyDb.getString(tinyDb.getString("loginUid") + "-token");
WatchRepository watch = new WatchRepository();
@ -130,6 +162,7 @@ public class StarredReposListAdapter extends RecyclerView.Adapter<StarredReposLi
}
});
}
context.startActivity(intent);

View File

@ -0,0 +1,53 @@
package org.mian.gitnex.database.dao;
import androidx.lifecycle.LiveData;
import androidx.room.Dao;
import androidx.room.Insert;
import androidx.room.Query;
import org.mian.gitnex.database.models.Drafts;
import org.mian.gitnex.database.models.DraftsWithRepositories;
import java.util.List;
/**
* Author M M Arif
*/
@Dao
public interface DraftsDao {
@Insert
long insertDraft(Drafts drafts);
@Query("SELECT * FROM drafts JOIN repositories ON repositories.repositoryId = drafts.draftRepositoryId WHERE draftAccountId = :accountId" +
" ORDER BY " +
"draftId DESC")
LiveData<List<DraftsWithRepositories>> fetchAllDrafts(int accountId);
@Query("SELECT * FROM drafts WHERE draftAccountId = :accountId ORDER BY draftId DESC")
LiveData<List<Drafts>> fetchDrafts(int accountId);
@Query("SELECT * FROM drafts WHERE draftAccountId = :accountId and draftRepositoryId = :repositoryId")
LiveData<Drafts> fetchSingleDraftByAccountIdAndRepositoryId(int accountId, int repositoryId);
@Query("SELECT * FROM drafts WHERE draftId = :draftId")
LiveData<Drafts> fetchDraftById(int draftId);
@Query("SELECT * FROM drafts WHERE issueId = :issueId")
LiveData<Drafts> fetchDraftByIssueId(int issueId);
@Query("SELECT count(draftId) FROM drafts WHERE issueId = :issueId AND draftRepositoryId = :draftRepositoryId")
Integer checkDraftDao(int issueId, int draftRepositoryId);
@Query("UPDATE drafts SET draftText= :draftText WHERE draftId = :draftId")
void updateDraft(String draftText, int draftId);
@Query("UPDATE drafts SET draftText= :draftText WHERE issueId = :issueId AND draftRepositoryId = :draftRepositoryId")
void updateDraftByIssueId(String draftText, int issueId, int draftRepositoryId);
@Query("DELETE FROM drafts WHERE draftId = :draftId")
void deleteByDraftId(int draftId);
@Query("DELETE FROM drafts WHERE draftAccountId = :accountId")
void deleteAllDrafts(int accountId);
}

View File

@ -0,0 +1,47 @@
package org.mian.gitnex.database.dao;
import androidx.lifecycle.LiveData;
import androidx.room.Dao;
import androidx.room.Insert;
import androidx.room.Query;
import org.mian.gitnex.database.models.Repositories;
import java.util.List;
/**
* Author M M Arif
*/
@Dao
public interface RepositoriesDao {
@Insert
long newRepository(Repositories repositories);
@Query("SELECT * FROM repositories ORDER BY repositoryId ASC")
LiveData<List<Repositories>> fetchAllRepositories();
@Query("SELECT * FROM repositories WHERE repoAccountId = :repoAccountId")
LiveData<List<Repositories>> getAllRepositoriesByAccountDao(int repoAccountId);
@Query("SELECT count(repositoryId) FROM repositories WHERE repoAccountId = :repoAccountId AND repositoryOwner = :repositoryOwner AND repositoryName = :repositoryName")
Integer checkRepositoryDao(int repoAccountId, String repositoryOwner, String repositoryName);
@Query("SELECT * FROM repositories WHERE repoAccountId = :repoAccountId AND repositoryOwner = :repositoryOwner AND repositoryName = :repositoryName")
Repositories getSingleRepositoryDao(int repoAccountId, String repositoryOwner, String repositoryName);
@Query("SELECT * FROM repositories WHERE repositoryId = :repositoryId")
Repositories fetchRepositoryByIdDao(int repositoryId);
@Query("SELECT * FROM repositories WHERE repositoryId = :repositoryId AND repoAccountId = :repoAccountId")
Repositories fetchRepositoryByAccountIdByRepositoryIdDao(int repositoryId, int repoAccountId);
@Query("UPDATE repositories SET repositoryOwner = :repositoryOwner, repositoryName = :repositoryName WHERE repositoryId = :repositoryId")
void updateRepositoryOwnerAndName(String repositoryOwner, String repositoryName, int repositoryId);
@Query("DELETE FROM repositories WHERE repositoryId = :repositoryId")
void deleteRepository(int repositoryId);
@Query("DELETE FROM repositories WHERE repoAccountId = :repoAccountId")
void deleteRepositoriesByAccount(int repoAccountId);
}

View File

@ -0,0 +1,53 @@
package org.mian.gitnex.database.dao;
import androidx.lifecycle.LiveData;
import androidx.room.Dao;
import androidx.room.Insert;
import androidx.room.Query;
import org.mian.gitnex.database.models.UserAccounts;
import java.util.List;
/**
* Author M M Arif
*/
@Dao
public interface UserAccountsDao {
@Insert
void newAccount(UserAccounts userAccounts);
@Query("SELECT * FROM userAccounts ORDER BY accountId ASC")
LiveData<List<UserAccounts>> fetchAllAccounts();
@Query("SELECT COUNT(accountId) FROM userAccounts WHERE accountName = :accountName")
LiveData<Integer> getCount(String accountName);
@Query("SELECT * FROM userAccounts WHERE accountName = :accountName")
UserAccounts fetchRowByAccount_(String accountName);
@Query("SELECT * FROM userAccounts WHERE accountId = :accountId")
UserAccounts fetchRowByAccountId(int accountId);
@Query("UPDATE userAccounts SET serverVersion = :serverVersion WHERE accountId = :accountId")
void updateServerVersion(String serverVersion, int accountId);
@Query("UPDATE userAccounts SET accountName = :accountName WHERE accountId = :accountId")
void updateAccountName(String accountName, int accountId);
@Query("UPDATE userAccounts SET token = :token WHERE accountId = :accountId")
void updateAccountToken(int accountId, String token);
@Query("UPDATE userAccounts SET instanceUrl = :instanceUrl, token = :token WHERE accountId = :accountId")
void updateHostInfo(String instanceUrl, String token, int accountId);
@Query("UPDATE userAccounts SET userName = :userName WHERE accountId = :accountId")
void updateUserName(String userName, int accountId);
@Query("UPDATE userAccounts SET instanceUrl = :instanceUrl, token = :token, userName = :userName, serverVersion = :serverVersion WHERE accountId = :accountId")
void updateAll(String instanceUrl, String token, String userName, String serverVersion, int accountId);
@Query("DELETE FROM userAccounts WHERE accountId = :accountId")
void deleteAccount(int accountId);
}

View File

@ -0,0 +1,55 @@
package org.mian.gitnex.database.db;
import android.content.Context;
import androidx.annotation.NonNull;
import androidx.room.Database;
import androidx.room.Room;
import androidx.room.RoomDatabase;
import androidx.room.migration.Migration;
import androidx.sqlite.db.SupportSQLiteDatabase;
import org.mian.gitnex.database.dao.DraftsDao;
import org.mian.gitnex.database.dao.RepositoriesDao;
import org.mian.gitnex.database.dao.UserAccountsDao;
import org.mian.gitnex.database.models.Drafts;
import org.mian.gitnex.database.models.Repositories;
import org.mian.gitnex.database.models.UserAccounts;
/**
* Author M M Arif
*/
@Database(entities = {Drafts.class, Repositories.class, UserAccounts.class},
version = 4, exportSchema = false)
public abstract class GitnexDatabase extends RoomDatabase {
private static GitnexDatabase gitnexDatabase;
public static GitnexDatabase getDatabaseInstance(Context context) {
if (gitnexDatabase == null) {
String DB_NAME = "gitnex";
gitnexDatabase = Room.databaseBuilder(context, GitnexDatabase.class, DB_NAME)
//.fallbackToDestructiveMigration()
//.addMigrations(MIGRATION_3_4)
.build();
}
return gitnexDatabase;
}
public abstract DraftsDao draftsDao();
public abstract RepositoriesDao repositoriesDao();
public abstract UserAccountsDao userAccountsDao();
private static final Migration MIGRATION_3_4 = new Migration(3, 4) {
@Override
public void migrate(@NonNull SupportSQLiteDatabase database) {
//database.execSQL("DROP TABLE Drafts");
//database.execSQL("ALTER TABLE 'Drafts' ADD COLUMN 'draftType' TEXT");
}
};
}

View File

@ -0,0 +1,83 @@
package org.mian.gitnex.database.models;
import androidx.annotation.Nullable;
import androidx.room.Entity;
import androidx.room.ForeignKey;
import androidx.room.Index;
import androidx.room.PrimaryKey;
import java.io.Serializable;
import static androidx.room.ForeignKey.CASCADE;
/**
* Author M M Arif
*/
@Entity(tableName = "Drafts", foreignKeys = @ForeignKey(entity = Repositories.class,
parentColumns = "repositoryId",
childColumns = "draftRepositoryId",
onDelete = CASCADE),
indices = {@Index("draftRepositoryId")})
public class Drafts implements Serializable {
@PrimaryKey(autoGenerate = true)
private int draftId;
private int draftRepositoryId;
private int draftAccountId;
private int issueId;
private String draftText;
@Nullable
private String draftType;
public int getDraftId() {
return draftId;
}
public void setDraftId(int draftId) {
this.draftId = draftId;
}
public int getDraftRepositoryId() {
return draftRepositoryId;
}
public void setDraftRepositoryId(int draftRepositoryId) {
this.draftRepositoryId = draftRepositoryId;
}
public int getDraftAccountId() {
return draftAccountId;
}
public void setDraftAccountId(int draftAccountId) {
this.draftAccountId = draftAccountId;
}
public int getIssueId() {
return issueId;
}
public void setIssueId(int issueId) {
this.issueId = issueId;
}
public String getDraftText() {
return draftText;
}
public void setDraftText(String draftText) {
this.draftText = draftText;
}
@Nullable
public String getDraftType() {
return draftType;
}
public void setDraftType(@Nullable String draftType) {
this.draftType = draftType;
}
}

View File

@ -0,0 +1,122 @@
package org.mian.gitnex.database.models;
/**
* Author M M Arif
*/
public class DraftsWithRepositories {
private int repositoryId;
private int draftId;
private int repoAccountId;
private String repositoryOwner;
private String repositoryName;
private int draftRepositoryId;
private int draftAccountId;
private int issueId;
private String draftText;
private String draftType;
public int getRepositoryId() {
return repositoryId;
}
public void setRepositoryId(int repositoryId) {
this.repositoryId = repositoryId;
}
public int getDraftId() {
return draftId;
}
public void setDraftId(int draftId) {
this.draftId = draftId;
}
public int getRepoAccountId() {
return repoAccountId;
}
public void setRepoAccountId(int repoAccountId) {
this.repoAccountId = repoAccountId;
}
public String getRepositoryOwner() {
return repositoryOwner;
}
public void setRepositoryOwner(String repositoryOwner) {
this.repositoryOwner = repositoryOwner;
}
public String getRepositoryName() {
return repositoryName;
}
public void setRepositoryName(String repositoryName) {
this.repositoryName = repositoryName;
}
public int getDraftRepositoryId() {
return draftRepositoryId;
}
public void setDraftRepositoryId(int draftRepositoryId) {
this.draftRepositoryId = draftRepositoryId;
}
public int getDraftAccountId() {
return draftAccountId;
}
public void setDraftAccountId(int draftAccountId) {
this.draftAccountId = draftAccountId;
}
public int getIssueId() {
return issueId;
}
public void setIssueId(int issueId) {
this.issueId = issueId;
}
public String getDraftText() {
return draftText;
}
public void setDraftText(String draftText) {
this.draftText = draftText;
}
public String getDraftType() {
return draftType;
}
public void setDraftType(String draftType) {
this.draftType = draftType;
}
}

View File

@ -0,0 +1,59 @@
package org.mian.gitnex.database.models;
import androidx.room.Entity;
import androidx.room.ForeignKey;
import androidx.room.Index;
import androidx.room.PrimaryKey;
import java.io.Serializable;
import static androidx.room.ForeignKey.CASCADE;
/**
* Author M M Arif
*/
@Entity(tableName = "repositories", foreignKeys = @ForeignKey(entity = UserAccounts.class,
parentColumns = "accountId",
childColumns = "repoAccountId",
onDelete = CASCADE),
indices = {@Index("repoAccountId")})
public class Repositories implements Serializable {
@PrimaryKey(autoGenerate = true)
private int repositoryId;
private int repoAccountId;
private String repositoryOwner;
private String repositoryName;
public int getRepositoryId() {
return repositoryId;
}
public void setRepositoryId(int repositoryId) {
this.repositoryId = repositoryId;
}
public int getRepoAccountId() {
return repoAccountId;
}
public void setRepoAccountId(int repoAccountId) {
this.repoAccountId = repoAccountId;
}
public String getRepositoryOwner() {
return repositoryOwner;
}
public void setRepositoryOwner(String repositoryOwner) {
this.repositoryOwner = repositoryOwner;
}
public String getRepositoryName() {
return repositoryName;
}
public void setRepositoryName(String repositoryName) {
this.repositoryName = repositoryName;
}
}

View File

@ -0,0 +1,75 @@
package org.mian.gitnex.database.models;
import androidx.annotation.Nullable;
import androidx.room.Entity;
import androidx.room.PrimaryKey;
import java.io.Serializable;
/**
* Author M M Arif
*/
@Entity(tableName = "userAccounts")
public class UserAccounts implements Serializable {
@PrimaryKey(autoGenerate = true)
private int accountId;
@Nullable
private String accountName;
private String instanceUrl;
private String userName;
private String token;
@Nullable
private String serverVersion;
public int getAccountId() {
return accountId;
}
public void setAccountId(int accountId) {
this.accountId = accountId;
}
@Nullable
public String getAccountName() {
return accountName;
}
public void setAccountName(@Nullable String accountName) {
this.accountName = accountName;
}
public String getInstanceUrl() {
return instanceUrl;
}
public void setInstanceUrl(String instanceUrl) {
this.instanceUrl = instanceUrl;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
@Nullable
public String getServerVersion() {
return serverVersion;
}
public void setServerVersion(@Nullable String serverVersion) {
this.serverVersion = serverVersion;
}
}

View File

@ -0,0 +1,156 @@
package org.mian.gitnex.database.repository;
import android.content.Context;
import android.os.AsyncTask;
import android.util.Log;
import androidx.lifecycle.LiveData;
import org.mian.gitnex.database.dao.DraftsDao;
import org.mian.gitnex.database.db.GitnexDatabase;
import org.mian.gitnex.database.models.Drafts;
import org.mian.gitnex.database.models.DraftsWithRepositories;
import org.mian.gitnex.helpers.StaticGlobalVariables;
import java.util.List;
import java.util.concurrent.ExecutionException;
/**
* Author M M Arif
*/
public class DraftsRepository {
private static DraftsDao draftsDao;
private static long draftId;
public DraftsRepository(Context context) {
GitnexDatabase db;
db = GitnexDatabase.getDatabaseInstance(context);
draftsDao = db.draftsDao();
}
public long insertDraft(int repositoryId, int draftAccountId, int issueId, String draftText, String draftType) {
Drafts drafts = new Drafts();
drafts.setDraftRepositoryId(repositoryId);
drafts.setDraftAccountId(draftAccountId);
drafts.setIssueId(issueId);
drafts.setDraftText(draftText);
drafts.setDraftType(draftType);
return insertDraftAsyncTask(drafts);
}
private static long insertDraftAsyncTask(final Drafts drafts) {
try {
new AsyncTask<Void, Void, Long>() {
@Override
protected Long doInBackground(Void... voids) {
draftId = draftsDao.insertDraft(drafts);
return draftId;
}
@Override
protected void onPostExecute(Long draftId) {
super.onPostExecute(draftId);
}
}.execute().get();
}
catch(ExecutionException | InterruptedException e) {
Log.e(StaticGlobalVariables.draftsRepository, e.toString());
}
return draftId;
}
public Integer checkDraft(int issueId, int draftRepositoryId) throws ExecutionException, InterruptedException {
return new DraftsRepository.checkDraftAsyncTask(issueId, draftRepositoryId).execute().get();
}
private static class checkDraftAsyncTask extends AsyncTask<Void, Void, Integer> {
int issueId;
int draftRepositoryId;
checkDraftAsyncTask(int issueId, int draftRepositoryId) {
this.issueId = issueId;
this.draftRepositoryId = draftRepositoryId;
}
@Override
protected Integer doInBackground(Void... params) {
return draftsDao.checkDraftDao(issueId, draftRepositoryId);
}
}
public LiveData<List<DraftsWithRepositories>> getDrafts(int accountId) {
return draftsDao.fetchAllDrafts(accountId);
}
public LiveData<Drafts> getDraftByIssueId(int issueId) {
return draftsDao.fetchDraftByIssueId(issueId);
}
public static void deleteSingleDraft(final int draftId) {
final LiveData<Drafts> draft = draftsDao.fetchDraftById(draftId);
if(draft != null) {
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... voids) {
draftsDao.deleteByDraftId(draftId);
return null;
}
}.execute();
}
}
public static void deleteAllDrafts(final int accountId) {
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... voids) {
draftsDao.deleteAllDrafts(accountId);
return null;
}
}.execute();
}
public static void updateDraft(final String draftText, final int draftId) {
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... voids) {
draftsDao.updateDraft(draftText, draftId);
return null;
}
}.execute();
}
public static void updateDraftByIssueIdAsycTask(final String draftText, final int issueId, final int draftRepositoryId) {
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... voids) {
draftsDao.updateDraftByIssueId(draftText, issueId, draftRepositoryId);
return null;
}
}.execute();
}
}

View File

@ -0,0 +1,189 @@
package org.mian.gitnex.database.repository;
import android.content.Context;
import android.os.AsyncTask;
import android.util.Log;
import androidx.lifecycle.LiveData;
import org.mian.gitnex.database.dao.RepositoriesDao;
import org.mian.gitnex.database.db.GitnexDatabase;
import org.mian.gitnex.database.models.Repositories;
import org.mian.gitnex.helpers.StaticGlobalVariables;
import java.util.List;
import java.util.concurrent.ExecutionException;
/**
* Author M M Arif
*/
public class RepositoriesRepository {
private static RepositoriesDao repositoriesDao;
private static long repositoryId;
public RepositoriesRepository(Context context) {
GitnexDatabase db;
db = GitnexDatabase.getDatabaseInstance(context);
repositoriesDao = db.repositoriesDao();
}
public long insertRepository(int repoAccountId, String repositoryOwner, String repositoryName) {
Repositories repositories = new Repositories();
repositories.setRepoAccountId(repoAccountId);
repositories.setRepositoryOwner(repositoryOwner);
repositories.setRepositoryName(repositoryName);
return insertRepositoryAsyncTask(repositories);
}
private static long insertRepositoryAsyncTask(final Repositories repositories) {
try {
new AsyncTask<Void, Void, Long>() {
@Override
protected Long doInBackground(Void... voids) {
repositoryId = repositoriesDao.newRepository(repositories);
return repositoryId;
}
@Override
protected void onPostExecute(Long repositoryId) {
super.onPostExecute(repositoryId);
}
}.execute().get();
}
catch(ExecutionException | InterruptedException e) {
Log.e(StaticGlobalVariables.repositoriesRepository, e.toString());
}
return repositoryId;
}
public Repositories getRepository(int repoAccountId, String repositoryOwner, String repositoryName) throws ExecutionException, InterruptedException {
return new RepositoriesRepository.getRepositoryAsyncTask(repoAccountId, repositoryOwner, repositoryName).execute().get();
}
private static class getRepositoryAsyncTask extends AsyncTask<Void, Void, Repositories> {
int repoAccountId;
String repositoryOwner;
String repositoryName;
getRepositoryAsyncTask(int repoAccountId, String repositoryOwner, String repositoryName) {
this.repoAccountId = repoAccountId;
this.repositoryOwner = repositoryOwner;
this.repositoryName = repositoryName;
}
@Override
protected Repositories doInBackground(Void... params) {
return repositoriesDao.getSingleRepositoryDao(repoAccountId, repositoryOwner, repositoryName);
}
}
public LiveData<List<Repositories>> getAllRepositories() {
return repositoriesDao.fetchAllRepositories();
}
public LiveData<List<Repositories>> getAllRepositoriesByAccount(int repoAccountId) {
return repositoriesDao.getAllRepositoriesByAccountDao(repoAccountId);
}
public Integer checkRepository(int repoAccountId, String repositoryOwner, String repositoryName) throws ExecutionException, InterruptedException {
return new RepositoriesRepository.checkRepositoryAsyncTask(repoAccountId, repositoryOwner, repositoryName).execute().get();
}
private static class checkRepositoryAsyncTask extends AsyncTask<Void, Void, Integer> {
int repoAccountId;
String repositoryOwner;
String repositoryName;
checkRepositoryAsyncTask(int repoAccountId, String repositoryOwner, String repositoryName) {
this.repoAccountId = repoAccountId;
this.repositoryOwner = repositoryOwner;
this.repositoryName = repositoryName;
}
@Override
protected Integer doInBackground(Void... params) {
return repositoriesDao.checkRepositoryDao(repoAccountId, repositoryOwner, repositoryName);
}
}
public Repositories fetchRepositoryById(int repositoryId) throws ExecutionException, InterruptedException {
return new RepositoriesRepository.getRepositoryByIdAsyncTask().execute(repositoryId).get();
}
private static class getRepositoryByIdAsyncTask extends AsyncTask<Integer, Void, Repositories> {
@Override
protected Repositories doInBackground(Integer... params) {
return repositoriesDao.fetchRepositoryByIdDao(params[0]);
}
}
public Repositories fetchRepositoryByAccountIdByRepositoryId(int repositoryId, int repoAccountId) throws ExecutionException, InterruptedException {
return new RepositoriesRepository.getRepositoryByAccountIdByRepositoryIdAsyncTask().execute(repositoryId, repoAccountId).get();
}
private static class getRepositoryByAccountIdByRepositoryIdAsyncTask extends AsyncTask<Integer, Void, Repositories> {
@Override
protected Repositories doInBackground(Integer... params) {
return repositoriesDao.fetchRepositoryByAccountIdByRepositoryIdDao(params[0], params[1]);
}
}
public static void deleteRepositoriesByAccount(final int repoAccountId) {
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... voids) {
repositoriesDao.deleteRepositoriesByAccount(repoAccountId);
return null;
}
}.execute();
}
public static void deleteRepository(final int repositoryId) {
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... voids) {
repositoriesDao.deleteRepository(repositoryId);
return null;
}
}.execute();
}
}

View File

@ -0,0 +1,110 @@
package org.mian.gitnex.database.repository;
import android.content.Context;
import android.os.AsyncTask;
import androidx.lifecycle.LiveData;
import org.mian.gitnex.database.dao.UserAccountsDao;
import org.mian.gitnex.database.db.GitnexDatabase;
import org.mian.gitnex.database.models.UserAccounts;
import java.util.List;
import java.util.concurrent.ExecutionException;
/**
* Author M M Arif
*/
public class UserAccountsRepository {
private static UserAccountsDao userAccountsDao;
public UserAccountsRepository(Context context) {
GitnexDatabase db;
db = GitnexDatabase.getDatabaseInstance(context);
userAccountsDao = db.userAccountsDao();
}
public void insertNewAccount(String accountName, String instanceUrl, String userName, String token, String serverVersion) {
UserAccounts userAccounts = new UserAccounts();
userAccounts.setAccountName(accountName);
userAccounts.setInstanceUrl(instanceUrl);
userAccounts.setUserName(userName);
userAccounts.setToken(token);
userAccounts.setServerVersion(serverVersion);
insertNewAccountAsync(userAccounts);
}
private static void insertNewAccountAsync(final UserAccounts userAccounts) {
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... voids) {
userAccountsDao.newAccount(userAccounts);
return null;
}
}.execute();
}
public static void updateServerVersion(final String serverVersion, final int accountId) {
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... voids) {
userAccountsDao.updateServerVersion(serverVersion, accountId);
return null;
}
}.execute();
}
public static void updateToken(final int accountId, final String token) {
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... voids) {
userAccountsDao.updateAccountToken(accountId, token);
return null;
}
}.execute();
}
public UserAccounts getAccountData(String accountName) throws ExecutionException, InterruptedException {
return new GetAccountByNameAsyncTask().execute(accountName).get();
}
private static class GetAccountByNameAsyncTask extends AsyncTask<String, Void, UserAccounts>
{
@Override
protected UserAccounts doInBackground(String... params) {
return userAccountsDao.fetchRowByAccount_(params[0]);
}
}
public static LiveData<Integer> getCount(String accountName) {
return userAccountsDao.getCount(accountName);
}
public LiveData<List<UserAccounts>> getAllAccounts() {
return userAccountsDao.fetchAllAccounts();
}
public static void deleteAccount(final int accountId) {
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... voids) {
userAccountsDao.deleteAccount(accountId);
return null;
}
}.execute();
}
}

View File

@ -0,0 +1,58 @@
package org.mian.gitnex.fragments;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
import org.mian.gitnex.R;
import org.mian.gitnex.helpers.StaticGlobalVariables;
/**
* Author M M Arif
*/
public class BottomSheetDraftsFragment extends BottomSheetDialogFragment {
private String TAG = StaticGlobalVariables.tagDraftsBottomSheet;
private BottomSheetDraftsFragment.BottomSheetListener bmListener;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.bottom_sheet_drafts, container, false);
TextView deleteAllDrafts = v.findViewById(R.id.deleteAllDrafts);
deleteAllDrafts.setOnClickListener(v1 -> {
dismiss();
bmListener.onButtonClicked("deleteDrafts");
});
return v;
}
public interface BottomSheetListener {
void onButtonClicked(String text);
}
@Override
public void onAttach(@NonNull Context context) {
super.onAttach(context);
try {
bmListener = (BottomSheetDraftsFragment.BottomSheetListener) context;
}
catch (ClassCastException e) {
Log.e(TAG, e.toString());
}
}
}

View File

@ -0,0 +1,138 @@
package org.mian.gitnex.fragments;
import android.content.Context;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import android.os.Handler;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import org.mian.gitnex.R;
import org.mian.gitnex.adapters.DraftsAdapter;
import org.mian.gitnex.database.models.DraftsWithRepositories;
import org.mian.gitnex.database.repository.DraftsRepository;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.util.TinyDB;
import java.util.ArrayList;
import java.util.List;
/**
* Author M M Arif
*/
public class DraftsFragment extends Fragment {
private Context ctx;
private DraftsAdapter adapter;
private RecyclerView mRecyclerView;
private DraftsRepository draftsRepository;
private TextView noData;
private List<DraftsWithRepositories> draftsList_;
private int currentActiveAccountId;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_drafts, container, false);
ctx = getContext();
setHasOptionsMenu(true);
TinyDB tinyDb = new TinyDB(ctx);
draftsList_ = new ArrayList<>();
draftsRepository = new DraftsRepository(ctx);
noData = v.findViewById(R.id.noData);
mRecyclerView = v.findViewById(R.id.recyclerView);
final SwipeRefreshLayout swipeRefresh = v.findViewById(R.id.pullToRefresh);
mRecyclerView.setHasFixedSize(true);
mRecyclerView.setLayoutManager(new LinearLayoutManager(ctx));
DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(mRecyclerView.getContext(),
DividerItemDecoration.VERTICAL);
mRecyclerView.addItemDecoration(dividerItemDecoration);
adapter = new DraftsAdapter(getContext(), draftsList_);
swipeRefresh.setOnRefreshListener(() -> new Handler().postDelayed(() -> {
draftsList_.clear();
swipeRefresh.setRefreshing(false);
fetchDataAsync(1);
}, 250));
currentActiveAccountId = tinyDb.getInt("currentActiveAccountId");
fetchDataAsync(currentActiveAccountId);
return v;
}
private void fetchDataAsync(int accountId) {
draftsRepository.getDrafts(accountId).observe(getViewLifecycleOwner(), drafts -> {
assert drafts != null;
if(drafts.size() > 0) {
draftsList_.clear();
noData.setVisibility(View.GONE);
draftsList_.addAll(drafts);
adapter.notifyDataSetChanged();
mRecyclerView.setAdapter(adapter);
}
else {
noData.setVisibility(View.VISIBLE);
}
});
}
@Override
public void onResume() {
super.onResume();
draftsList_.clear();
fetchDataAsync(currentActiveAccountId);
}
public void deleteAllDrafts(int accountId) {
if(draftsList_.size() > 0) {
DraftsRepository.deleteAllDrafts(accountId);
draftsList_.clear();
adapter.notifyDataSetChanged();
Toasty.info(ctx, getResources().getString(R.string.draftsDeleteSuccess));
}
else {
Toasty.error(ctx, getResources().getString(R.string.draftsListEmptyError));
}
}
@Override
public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) {
inflater.inflate(R.menu.generic_nav_dotted_menu, menu);
super.onCreateOptionsMenu(menu, inflater);
}
}

View File

@ -50,6 +50,31 @@ public class AlertDialogs {
alertDialog.show();
}
public static void forceLogoutDialog(final Context context, String title, String message, String copyPositiveButton) {
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(context);
alertDialogBuilder
.setTitle(title)
.setMessage(message)
.setCancelable(false)
.setIcon(R.drawable.ic_info_outline_24dp)
.setPositiveButton(copyPositiveButton, (dialog, which) -> {
final TinyDB tinyDb = new TinyDB(context);
tinyDb.putBoolean("loggedInMode", false);
tinyDb.remove("basicAuthPassword");
tinyDb.putBoolean("basicAuthFlag", false);
Intent intent = new Intent(context, LoginActivity.class);
context.startActivity(intent);
dialog.dismiss();
});
AlertDialog alertDialog = alertDialogBuilder.create();
alertDialog.show();
}
public static void labelDeleteDialog(final Context context, final String labelTitle, final String labelId, String title, String message, String positiveButton, String negativeButton) {
new AlertDialog.Builder(context)

View File

@ -11,12 +11,21 @@ public interface StaticGlobalVariables {
int resultLimitOldGiteaInstances = 10; // Gitea 1.11 and below
// issues variables
String tagIssuesList = "IssuesListFragment";
int issuesPageInit = 1;
String issuesRequestType = "issues";
// pull request
String tagPullRequestsList = "PullRequestsListFragment";
int prPageInit = 1;
// drafts
String draftTypeComment = "comment";
String draftTypeIssue = "issue";
// TAGS
String tagPullRequestsList = "PullRequestsListFragment";
String tagIssuesList = "IssuesListFragment";
String draftsRepository = "DraftsRepository";
String repositoriesRepository = "RepositoriesRepository";
String replyToIssueActivity = "ReplyToIssueActivity";
String tagDraftsBottomSheet = "BottomSheetDraftsFragment";
}

View File

@ -0,0 +1,11 @@
package org.mian.gitnex.viewmodels;
import androidx.lifecycle.ViewModel;
/**
* Author M M Arif
*/
public class DraftsDatabaseViewModel extends ViewModel {
}

View File

@ -0,0 +1,11 @@
package org.mian.gitnex.viewmodels;
import androidx.lifecycle.ViewModel;
/**
* Author M M Arif
*/
public class RepositoriesDatabaseViewModel extends ViewModel {
}

View File

@ -0,0 +1,25 @@
package org.mian.gitnex.viewmodels;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.ViewModel;
import org.mian.gitnex.database.repository.UserAccountsRepository;
/**
* Author M M Arif
*/
public class UserAccountsDatabaseViewModel extends ViewModel {
private static LiveData<Integer> totalCount;
public static LiveData<Integer> getCount(String accountName) {
if (totalCount == null) {
totalCount = UserAccountsRepository.getCount(accountName);
}
return totalCount;
}
}

View File

@ -0,0 +1,5 @@
<vector android:autoMirrored="true" android:height="24dp"
android:tint="#FFFFFF" android:viewportHeight="24.0"
android:viewportWidth="24.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M21.99,8c0,-0.72 -0.37,-1.35 -0.94,-1.7L12,1 2.95,6.3C2.38,6.65 2,7.28 2,8v10c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2l-0.01,-10zM12,13L3.74,7.84 12,3l8.26,4.84L12,13z"/>
</vector>

View File

@ -0,0 +1,36 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingBottom="8dp"
android:background="?attr/primaryBackgroundColor"
android:paddingTop="8dp">
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:orientation="vertical"
android:layout_height="wrap_content">
<TextView
android:id="@+id/deleteAllDrafts"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:text="@string/deleteAllDrafts"
android:drawableStart="@drawable/ic_delete"
android:drawablePadding="24dp"
android:textColor="?attr/primaryTextColor"
android:textSize="16sp"
android:padding="16dp" />
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</LinearLayout>

View File

@ -0,0 +1,40 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
tools:context=".activities.RepoDetailActivity"
android:id="@+id/draftsFrame"
android:background="?attr/primaryBackgroundColor"
android:visibility="visible">
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
android:id="@+id/pullToRefresh"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/primaryBackgroundColor"
android:padding="4dp"
android:scrollbars="vertical"
/>
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
<TextView
android:id="@+id/noData"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="15dp"
android:gravity="center"
android:text="@string/noDataFound"
android:textColor="?attr/primaryTextColor"
android:textSize="20sp"
android:visibility="gone" />
</LinearLayout>

View File

@ -0,0 +1,88 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:tools="http://schemas.android.com/tools"
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/layoutDraftsFrame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:fitsSystemWindows="true"
android:orientation="vertical"
android:layout_margin="10dp"
android:background="?attr/primaryBackgroundColor"
tools:context=".activities.MainActivity">
<TextView
android:id="@+id/repoId"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:visibility="gone" />
<TextView
android:id="@+id/draftId"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:visibility="gone" />
<TextView
android:id="@+id/issueNumber"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:visibility="gone" />
<TextView
android:id="@+id/issueType"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:visibility="gone" />
<TextView
android:id="@+id/repoOwner"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:visibility="gone" />
<TextView
android:id="@+id/repoName"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:visibility="gone" />
<LinearLayout
android:id="@+id/frameDraftInfo"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginBottom="10dp">
<TextView
android:id="@+id/repoInfo"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight=".95"
android:layout_gravity="start"
android:textColor="?attr/primaryTextColor"
android:textSize="16sp" />
<ImageView
android:id="@+id/deleteDraft"
android:layout_weight=".05"
android:layout_width="10dp"
android:layout_height="20dp"
android:layout_gravity="end"
android:src="@drawable/ic_delete"
android:contentDescription="@string/menuDeleteText" />
</LinearLayout>
<TextView
android:id="@+id/draftText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="0dp"
android:textColor="?attr/primaryTextColor"
android:textSize="12sp"
android:text="@string/noDataFound" />
</LinearLayout>

View File

@ -20,6 +20,9 @@
<item android:id="@+id/nav_explore"
android:icon="@drawable/ic_search"
android:title="@string/navExplore" />
<item android:id="@+id/nav_comments_draft"
android:icon="@drawable/ic_drafts_24dp"
android:title="@string/navDrafts" />
<item android:id="@+id/nav_profile"
android:icon="@drawable/ic_person_24dp"
android:title="@string/navProfile" />

View File

@ -540,6 +540,8 @@
<string name="unWatchRepository">Unwatch Repository</string>
<string name="watchRepositorySuccess">Repository added to watch list</string>
<string name="unWatchRepositorySuccess">Repository removed from watch list</string>
<string name="navDrafts">Drafts</string>
<string name="pageTitleDrafts">Drafts</string>
<string name="filesBreadcrumbRoot" translatable="false">Root</string>
<string name="versionUnsupportedOld">Unsupported old version(%1$s) of Gitea detected. Please update to latest stable version. If you continue, the app may not function properly.</string>
@ -628,6 +630,15 @@
<string name="setCrashReports">Crash reports</string>
<string name="crashMessage">You can tap the OK button to send the crash report by email. It will help to fix it :)\n\nYou can also add additional content in the email. Thank you!</string>
<string name="forceLogoutDialogHeader">Re-login is Required</string>
<string name="forceLogoutDialogDescription">There are new updates introduced in the recent version, for compatibility the app will log you out to reinitiate the process. Sorry for the inconvience.\n\nPlease click the Logout button to continue.</string>
<string name="deleteAllDrafts">Delete All Drafts</string>
<string name="draftsListEmptyError">No drafts found</string>
<string name="draftsDeleteSuccess">Drafts deleted successfully</string>
<string name="draftsSingleDeleteSuccess">Draft deleted successfully</string>
<string name="deleteAllDraftsDialogMessage">This will delete all the drafts for this account. \n\nProceed with deletion?</string>
<string name="appreanceHintText">Themes, fonts, badges, code block theme</string>
<string name="fileViewerHintText">PDF mode, source code theme</string>
<string name="securityHintText">SSL certificates</string>