diff --git a/app/build.gradle b/app/build.gradle index 088e7628a..513be6a83 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -122,7 +122,7 @@ dependencies { implementation 'androidx.appcompat:appcompat:1.7.0' implementation 'androidx.core:core-ktx:1.13.1' implementation 'androidx.core:core-splashscreen:1.0.1' - implementation 'androidx.fragment:fragment:1.8.6' + implementation 'androidx.fragment:fragment:1.8.5' implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.7' implementation 'androidx.preference:preference:1.2.1' implementation 'androidx.recyclerview:recyclerview-selection:1.1.0' @@ -139,7 +139,7 @@ dependencies { implementation 'com.squareup.retrofit2:retrofit:2.11.0' // Gson - implementation 'com.google.code.gson:gson:2.12.1' + implementation 'com.google.code.gson:gson:2.11.0' // ReactiveX implementation 'io.reactivex.rxjava2:rxjava:2.2.21' diff --git a/app/src/main/java/it/niedermann/owncloud/notes/edit/BaseNoteFragment.java b/app/src/main/java/it/niedermann/owncloud/notes/edit/BaseNoteFragment.java index fbbf86c2a..903bce104 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/edit/BaseNoteFragment.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/edit/BaseNoteFragment.java @@ -122,7 +122,7 @@ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceStat if (content == null) { throw new IllegalArgumentException(PARAM_NOTE_ID + " is not given, argument " + PARAM_NEWNOTE + " is missing and " + PARAM_CONTENT + " is missing."); } else { - note = new Note(-1, null, Calendar.getInstance(), NoteUtil.generateNoteTitle(content), content, getString(R.string.category_readonly), false, null, DBStatus.VOID, -1, "", 0, false); + note = new Note(-1, null, Calendar.getInstance(), NoteUtil.generateNoteTitle(content), content, getString(R.string.category_readonly), false, null, DBStatus.VOID, -1, "", 0, false, false); requireActivity().runOnUiThread(() -> onNoteLoaded(note)); requireActivity().invalidateOptionsMenu(); } diff --git a/app/src/main/java/it/niedermann/owncloud/notes/edit/EditNoteActivity.java b/app/src/main/java/it/niedermann/owncloud/notes/edit/EditNoteActivity.java index 345b278d7..ee24c2820 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/edit/EditNoteActivity.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/edit/EditNoteActivity.java @@ -302,7 +302,7 @@ private void launchNewNote() { if (content == null) { content = ""; } - final var newNote = new Note(null, Calendar.getInstance(), NoteUtil.generateNonEmptyNoteTitle(content, this), content, categoryTitle, favorite, null, false); + final var newNote = new Note(null, Calendar.getInstance(), NoteUtil.generateNonEmptyNoteTitle(content, this), content, categoryTitle, favorite, null, false, false); fragment = getNewNoteFragment(newNote); replaceFragment(); } diff --git a/app/src/main/java/it/niedermann/owncloud/notes/persistence/NotesRepository.java b/app/src/main/java/it/niedermann/owncloud/notes/persistence/NotesRepository.java index fa9eb594d..cffa91561 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/persistence/NotesRepository.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/persistence/NotesRepository.java @@ -480,7 +480,7 @@ public NotesListWidgetData getNoteListWidgetData(int appWidgetId) { @NonNull @MainThread public LiveData addNoteAndSync(Account account, Note note) { - final var entity = new Note(0, null, note.getModified(), note.getTitle(), note.getContent(), note.getCategory(), note.getFavorite(), note.getETag(), DBStatus.LOCAL_EDITED, account.getId(), generateNoteExcerpt(note.getContent(), note.getTitle()), 0, note.isShared()); + final var entity = new Note(0, null, note.getModified(), note.getTitle(), note.getContent(), note.getCategory(), note.getFavorite(), note.getETag(), DBStatus.LOCAL_EDITED, account.getId(), generateNoteExcerpt(note.getContent(), note.getTitle()), 0, note.isShared(), note.getReadonly()); final var ret = new MutableLiveData(); executor.submit(() -> ret.postValue(addNote(account.getId(), entity))); return map(ret, newNote -> { @@ -508,7 +508,7 @@ public Note addNote(long accountId, @NonNull Note note) { @MainThread public LiveData moveNoteToAnotherAccount(Account account, @NonNull Note note) { - final var fullNote = new Note(null, note.getModified(), note.getTitle(), note.getContent(), note.getCategory(), note.getFavorite(), null, note.isShared()); + final var fullNote = new Note(null, note.getModified(), note.getTitle(), note.getContent(), note.getCategory(), note.getFavorite(), null, note.isShared(), note.getReadonly()); fullNote.setStatus(DBStatus.LOCAL_EDITED); deleteNoteAndSync(account, note.getId()); return addNoteAndSync(account, fullNote); @@ -570,7 +570,7 @@ public Note updateNoteAndSync(@NonNull Account localAccount, @NonNull Note oldNo // https://github.com/nextcloud/notes-android/issues/1198 @Nullable final Long remoteId = db.getNoteDao().getRemoteId(oldNote.getId()); if (newContent == null) { - newNote = new Note(oldNote.getId(), remoteId, oldNote.getModified(), oldNote.getTitle(), oldNote.getContent(), oldNote.getCategory(), oldNote.getFavorite(), oldNote.getETag(), DBStatus.LOCAL_EDITED, localAccount.getId(), oldNote.getExcerpt(), oldNote.getScrollY(), oldNote.isShared()); + newNote = new Note(oldNote.getId(), remoteId, oldNote.getModified(), oldNote.getTitle(), oldNote.getContent(), oldNote.getCategory(), oldNote.getFavorite(), oldNote.getETag(), DBStatus.LOCAL_EDITED, localAccount.getId(), oldNote.getExcerpt(), oldNote.getScrollY(), oldNote.isShared(), oldNote.getReadonly()); } else { final String title; if (newTitle != null) { @@ -584,7 +584,7 @@ public Note updateNoteAndSync(@NonNull Account localAccount, @NonNull Note oldNo title = oldNote.getTitle(); } } - newNote = new Note(oldNote.getId(), remoteId, Calendar.getInstance(), title, newContent, oldNote.getCategory(), oldNote.getFavorite(), oldNote.getETag(), DBStatus.LOCAL_EDITED, localAccount.getId(), generateNoteExcerpt(newContent, title), oldNote.getScrollY(), oldNote.isShared()); + newNote = new Note(oldNote.getId(), remoteId, Calendar.getInstance(), title, newContent, oldNote.getCategory(), oldNote.getFavorite(), oldNote.getETag(), DBStatus.LOCAL_EDITED, localAccount.getId(), generateNoteExcerpt(newContent, title), oldNote.getScrollY(), oldNote.isShared(), oldNote.getReadonly()); } int rows = db.getNoteDao().updateNote(newNote); // if data was changed, set new status and schedule sync (with callback); otherwise invoke callback directly. diff --git a/app/src/main/java/it/niedermann/owncloud/notes/persistence/dao/NoteDao.java b/app/src/main/java/it/niedermann/owncloud/notes/persistence/dao/NoteDao.java index 2f04c77e9..6c1b48634 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/persistence/dao/NoteDao.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/persistence/dao/NoteDao.java @@ -38,14 +38,14 @@ public interface NoteDao { String getNoteById = "SELECT * FROM NOTE WHERE id = :id"; String count = "SELECT COUNT(*) FROM NOTE WHERE status != 'LOCAL_DELETED' AND accountId = :accountId"; String countFavorites = "SELECT COUNT(*) FROM NOTE WHERE status != 'LOCAL_DELETED' AND accountId = :accountId AND favorite = 1"; - String searchRecentByModified = "SELECT id, remoteId, accountId, title, favorite, isShared, excerpt, modified, category, status, '' as eTag, '' as content, 0 as scrollY FROM NOTE WHERE accountId = :accountId AND status != 'LOCAL_DELETED' AND (title LIKE :query OR content LIKE :query) ORDER BY favorite DESC, modified DESC"; - String searchRecentLexicographically = "SELECT id, remoteId, accountId, title, favorite, isShared, excerpt, modified, category, status, '' as eTag, '' as content, 0 as scrollY FROM NOTE WHERE accountId = :accountId AND status != 'LOCAL_DELETED' AND (title LIKE :query OR content LIKE :query) ORDER BY favorite DESC, title COLLATE LOCALIZED ASC"; - String searchFavoritesByModified = "SELECT id, remoteId, accountId, title, favorite, isShared, excerpt, modified, category, status, '' as eTag, '' as content, 0 as scrollY FROM NOTE WHERE accountId = :accountId AND status != 'LOCAL_DELETED' AND (title LIKE :query OR content LIKE :query) AND favorite = 1 ORDER BY modified DESC"; - String searchFavoritesLexicographically = "SELECT id, remoteId, accountId, title, favorite, isShared, excerpt, modified, category, status, '' as eTag, '' as content, 0 as scrollY FROM NOTE WHERE accountId = :accountId AND status != 'LOCAL_DELETED' AND (title LIKE :query OR content LIKE :query) AND favorite = 1 ORDER BY title COLLATE LOCALIZED ASC"; - String searchUncategorizedByModified = "SELECT id, remoteId, accountId, title, favorite, isShared, excerpt, modified, category, status, '' as eTag, '' as content, 0 as scrollY FROM NOTE WHERE accountId = :accountId AND status != 'LOCAL_DELETED' AND (title LIKE :query OR content LIKE :query) AND category = '' ORDER BY favorite DESC, modified DESC"; - String searchUncategorizedLexicographically = "SELECT id, remoteId, accountId, title, favorite, isShared, excerpt, modified, category, status, '' as eTag, '' as content, 0 as scrollY FROM NOTE WHERE accountId = :accountId AND status != 'LOCAL_DELETED' AND (title LIKE :query OR content LIKE :query) AND category = '' ORDER BY favorite DESC, title COLLATE LOCALIZED ASC"; - String searchCategoryByModified = "SELECT id, remoteId, accountId, title, favorite, isShared, excerpt, modified, category, status, '' as eTag, '' as content, 0 as scrollY FROM NOTE WHERE accountId = :accountId AND status != 'LOCAL_DELETED' AND (title LIKE :query OR content LIKE :query) AND (category = :category OR category LIKE :category || '/%') ORDER BY category, favorite DESC, modified DESC"; - String searchCategoryLexicographically = "SELECT id, remoteId, accountId, title, favorite, isShared, excerpt, modified, category, status, '' as eTag, '' as content, 0 as scrollY FROM NOTE WHERE accountId = :accountId AND status != 'LOCAL_DELETED' AND (title LIKE :query OR content LIKE :query) AND (category = :category OR category LIKE :category || '/%') ORDER BY category, favorite DESC, title COLLATE LOCALIZED ASC"; + String searchRecentByModified = "SELECT id, remoteId, accountId, title, favorite, isShared, readonly, excerpt, modified, category, status, '' as eTag, '' as content, 0 as scrollY FROM NOTE WHERE accountId = :accountId AND status != 'LOCAL_DELETED' AND (title LIKE :query OR content LIKE :query) ORDER BY favorite DESC, modified DESC"; + String searchRecentLexicographically = "SELECT id, remoteId, accountId, title, favorite, isShared, readonly, excerpt, modified, category, status, '' as eTag, '' as content, 0 as scrollY FROM NOTE WHERE accountId = :accountId AND status != 'LOCAL_DELETED' AND (title LIKE :query OR content LIKE :query) ORDER BY favorite DESC, title COLLATE LOCALIZED ASC"; + String searchFavoritesByModified = "SELECT id, remoteId, accountId, title, favorite, isShared, readonly, excerpt, modified, category, status, '' as eTag, '' as content, 0 as scrollY FROM NOTE WHERE accountId = :accountId AND status != 'LOCAL_DELETED' AND (title LIKE :query OR content LIKE :query) AND favorite = 1 ORDER BY modified DESC"; + String searchFavoritesLexicographically = "SELECT id, remoteId, accountId, title, favorite, isShared, readonly, excerpt, modified, category, status, '' as eTag, '' as content, 0 as scrollY FROM NOTE WHERE accountId = :accountId AND status != 'LOCAL_DELETED' AND (title LIKE :query OR content LIKE :query) AND favorite = 1 ORDER BY title COLLATE LOCALIZED ASC"; + String searchUncategorizedByModified = "SELECT id, remoteId, accountId, title, favorite, isShared, readonly, excerpt, modified, category, status, '' as eTag, '' as content, 0 as scrollY FROM NOTE WHERE accountId = :accountId AND status != 'LOCAL_DELETED' AND (title LIKE :query OR content LIKE :query) AND category = '' ORDER BY favorite DESC, modified DESC"; + String searchUncategorizedLexicographically = "SELECT id, remoteId, accountId, title, favorite, isShared, readonly, excerpt, modified, category, status, '' as eTag, '' as content, 0 as scrollY FROM NOTE WHERE accountId = :accountId AND status != 'LOCAL_DELETED' AND (title LIKE :query OR content LIKE :query) AND category = '' ORDER BY favorite DESC, title COLLATE LOCALIZED ASC"; + String searchCategoryByModified = "SELECT id, remoteId, accountId, title, favorite, isShared, readonly, excerpt, modified, category, status, '' as eTag, '' as content, 0 as scrollY FROM NOTE WHERE accountId = :accountId AND status != 'LOCAL_DELETED' AND (title LIKE :query OR content LIKE :query) AND (category = :category OR category LIKE :category || '/%') ORDER BY category, favorite DESC, modified DESC"; + String searchCategoryLexicographically = "SELECT id, remoteId, accountId, title, favorite, isShared, readonly, excerpt, modified, category, status, '' as eTag, '' as content, 0 as scrollY FROM NOTE WHERE accountId = :accountId AND status != 'LOCAL_DELETED' AND (title LIKE :query OR content LIKE :query) AND (category = :category OR category LIKE :category || '/%') ORDER BY category, favorite DESC, title COLLATE LOCALIZED ASC"; @Query(getNoteById) LiveData getNoteById$(long id); @@ -141,7 +141,7 @@ public interface NoteDao { * Gets a list of {@link Note} objects with filled {@link Note#id} and {@link Note#remoteId}, * where {@link Note#remoteId} is not null */ - @Query("SELECT id, remoteId, 0 as accountId, '' as title, 0 as favorite, 0 as isShared, '' as excerpt, 0 as modified, '' as eTag, 0 as status, '' as category, '' as content, 0 as scrollY FROM NOTE WHERE accountId = :accountId AND status != 'LOCAL_DELETED' AND remoteId IS NOT NULL") + @Query("SELECT id, remoteId, 0 as accountId, '' as title, 0 as favorite, 0 as isShared, 0 as readonly, '' as excerpt, 0 as modified, '' as eTag, 0 as status, '' as category, '' as content, 0 as scrollY FROM NOTE WHERE accountId = :accountId AND status != 'LOCAL_DELETED' AND remoteId IS NOT NULL") List getRemoteIdAndId(long accountId); /** diff --git a/app/src/main/java/it/niedermann/owncloud/notes/persistence/entity/Note.java b/app/src/main/java/it/niedermann/owncloud/notes/persistence/entity/Note.java index 84756ebbc..010493abf 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/persistence/entity/Note.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/persistence/entity/Note.java @@ -39,6 +39,7 @@ @Index(name = "IDX_NOTE_CATEGORY", value = "category"), @Index(name = "IDX_NOTE_FAVORITE", value = "favorite"), @Index(name = "IDX_NOTE_IS_SHARED", value = "isShared"), + @Index(name = "IDX_READONLY", value = "readonly"), @Index(name = "IDX_NOTE_MODIFIED", value = "modified"), @Index(name = "IDX_NOTE_REMOTEID", value = "remoteId"), @Index(name = "IDX_NOTE_STATUS", value = "status") @@ -86,6 +87,10 @@ public class Note implements Serializable, Item { @ColumnInfo(defaultValue = "0") private boolean isShared = false; + @Expose + @ColumnInfo(defaultValue = "0") + private boolean readonly = false; + @Expose @Nullable @SerializedName("etag") @@ -103,7 +108,7 @@ public Note() { } @Ignore - public Note(@Nullable Long remoteId, @Nullable Calendar modified, @NonNull String title, @NonNull String content, @NonNull String category, boolean favorite, @Nullable String eTag, boolean isShared) { + public Note(@Nullable Long remoteId, @Nullable Calendar modified, @NonNull String title, @NonNull String content, @NonNull String category, boolean favorite, @Nullable String eTag, boolean isShared, boolean readonly) { this.remoteId = remoteId; this.title = title; this.modified = modified; @@ -115,8 +120,8 @@ public Note(@Nullable Long remoteId, @Nullable Calendar modified, @NonNull Strin } @Ignore - public Note(long id, @Nullable Long remoteId, @Nullable Calendar modified, @NonNull String title, @NonNull String content, @NonNull String category, boolean favorite, @Nullable String etag, @NonNull DBStatus status, long accountId, @NonNull String excerpt, int scrollY, boolean isShared) { - this(remoteId, modified, title, content, category, favorite, etag, isShared); + public Note(long id, @Nullable Long remoteId, @Nullable Calendar modified, @NonNull String title, @NonNull String content, @NonNull String category, boolean favorite, @Nullable String etag, @NonNull DBStatus status, long accountId, @NonNull String excerpt, int scrollY, boolean isShared, boolean readonly) { + this(remoteId, modified, title, content, category, favorite, etag, isShared, readonly); this.id = id; this.status = status; this.accountId = accountId; @@ -202,6 +207,14 @@ public void setContent(@NonNull String content) { this.content = content; } + public boolean getReadonly() { + return readonly; + } + + public void setReadonly(boolean value) { + readonly = value; + } + public boolean getFavorite() { return favorite; } diff --git a/app/src/main/java/it/niedermann/owncloud/notes/persistence/sync/CapabilitiesDeserializer.java b/app/src/main/java/it/niedermann/owncloud/notes/persistence/sync/CapabilitiesDeserializer.java index 7cc6679d2..42efdcb18 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/persistence/sync/CapabilitiesDeserializer.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/persistence/sync/CapabilitiesDeserializer.java @@ -43,20 +43,6 @@ public class CapabilitiesDeserializer implements JsonDeserializer private static final String CAPABILITIES_FILES_SHARING = "files_sharing"; private static final String VERSION = "version"; - /* - if (capabilities != null && (capabilities.getFilesSharingPublicPasswordEnforced().isTrue() || - capabilities.getFilesSharingPublicAskForOptionalPassword().isTrue())) { - // password enforced by server, request to the user before trying to create - requestPasswordForShareViaLink(true, - capabilities.getFilesSharingPublicAskForOptionalPassword().isTrue()); - - } else { - // create without password if not enforced by server or we don't know if enforced; - fileOperationsHelper.shareFileViaPublicShare(file, null); - } - - password -> {JsonObject@32644} "{"enforced":false,"askForOptionalPassword":false}" - */ @Override public Capabilities deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { final var response = new Capabilities(); @@ -88,9 +74,11 @@ public Capabilities deserialize(JsonElement json, Type typeOfT, JsonDeserializat final var password = publicObject.getAsJsonObject("password"); final var enforced = password.getAsJsonPrimitive("enforced"); final var askForOptionalPassword = password.getAsJsonPrimitive("askForOptionalPassword"); + final var isReSharingAllowed = filesSharing.getAsJsonPrimitive("resharing"); response.setPublicPasswordEnforced(enforced.getAsBoolean()); response.setAskForOptionalPassword(askForOptionalPassword.getAsBoolean()); + response.setReSharingAllowed(isReSharingAllowed.getAsBoolean()); } if (capabilities.has(CAPABILITIES_NOTES)) { diff --git a/app/src/main/java/it/niedermann/owncloud/notes/share/NoteShareActivity.java b/app/src/main/java/it/niedermann/owncloud/notes/share/NoteShareActivity.java index 0401416eb..706bfac77 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/share/NoteShareActivity.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/share/NoteShareActivity.java @@ -14,6 +14,7 @@ import android.text.InputType; import android.text.TextUtils; import android.view.View; +import android.view.ViewGroup; import android.view.inputmethod.EditorInfo; import androidx.activity.result.ActivityResultLauncher; @@ -52,6 +53,7 @@ import it.niedermann.owncloud.notes.share.dialog.QuickSharingPermissionsBottomSheetDialog; import it.niedermann.owncloud.notes.share.dialog.ShareLinkToDialog; import it.niedermann.owncloud.notes.share.dialog.SharePasswordDialogFragment; +import it.niedermann.owncloud.notes.share.helper.AvatarLoader; import it.niedermann.owncloud.notes.share.helper.UsersAndGroupsSearchProvider; import it.niedermann.owncloud.notes.share.listener.NoteShareItemAction; import it.niedermann.owncloud.notes.share.listener.ShareeListAdapterListener; @@ -79,6 +81,7 @@ public class NoteShareActivity extends BrandedActivity implements ShareeListAdap private Account account; private ShareRepository repository; private Capabilities capabilities; + private final List shares = new ArrayList<>(); public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -99,7 +102,7 @@ private void initializeArguments() { throw new IllegalArgumentException("Account cannot be null"); } - executorService.schedule(() -> { + executorService.submit(() -> { try { final var ssoAcc = SingleAccountHelper.getCurrentSingleSignOnAccount(NoteShareActivity.this); repository = new ShareRepository(NoteShareActivity.this, ssoAcc); @@ -112,14 +115,19 @@ private void initializeArguments() { binding.pickContactEmailBtn.setOnClickListener(v -> checkContactPermission()); binding.btnShareButton.setOnClickListener(v -> ShareUtil.openShareDialog(this, note.getTitle(), note.getContent())); - setupView(); + if (note.getReadonly()) { + setupReadOnlySearchView(); + } else { + setupSearchView((SearchManager) getSystemService(Context.SEARCH_SERVICE), getComponentName()); + } + refreshCapabilitiesFromDB(); refreshSharesFromDB(); }); } catch (Exception e) { throw new RuntimeException(e); } - }, 0, TimeUnit.MICROSECONDS); + }); } @Override @@ -134,9 +142,22 @@ public void onStop() { UsersAndGroupsSearchConfig.INSTANCE.reset(); } - private void setupView() { - setShareWithYou(); - setupSearchView((SearchManager) getSystemService(Context.SEARCH_SERVICE), getComponentName()); + private void disableSearchView(View view) { + view.setEnabled(false); + + if (view instanceof ViewGroup viewGroup) { + for (int i = 0; i < viewGroup.getChildCount(); i++) { + disableSearchView(viewGroup.getChildAt(i)); + } + } + } + + private void setupReadOnlySearchView() { + binding.searchView.setIconifiedByDefault(false); + binding.searchView.setQueryHint(getResources().getString(R.string.note_share_activity_resharing_not_allowed)); + binding.searchView.setInputType(InputType.TYPE_NULL); + binding.pickContactEmailBtn.setVisibility(View.GONE); + disableSearchView(binding.searchView); } private void setupSearchView(@Nullable SearchManager searchManager, ComponentName componentName) { @@ -185,24 +206,26 @@ public boolean onQueryTextChange(String newText) { } final var isFederationShareAllowed = capabilities.getFederationShare(); - try(var cursor = provider.searchForUsersOrGroups(newText, isFederationShareAllowed)) { - runOnUiThread(() -> { - { - if (cursor == null || cursor.getCount() == 0) { - return; - } + try { + var cursor = provider.searchForUsersOrGroups(newText, isFederationShareAllowed); - if (binding.searchView.getVisibility() == View.VISIBLE) { - suggestionAdapter.swapCursor(cursor); - } + if (cursor == null || cursor.getCount() == 0) { + return; + } - binding.progressBar.setVisibility(View.GONE); + runOnUiThread(() -> { + if (binding.searchView.getVisibility() == View.VISIBLE) { + suggestionAdapter.swapCursor(cursor); } + + binding.progressBar.setVisibility(View.GONE); }); + } catch (Exception e) { Log_OC.d(TAG, "Exception setupSearchView.onQueryTextChange: " + e); runOnUiThread(() -> binding.progressBar.setVisibility(View.GONE)); } + }, SEARCH_DELAY_MS, TimeUnit.MILLISECONDS); return false; @@ -244,13 +267,38 @@ private void navigateNoteShareDetail(String shareWith, int shareType) { } private boolean accountOwnsFile() { - String displayName = account.getDisplayName(); - return TextUtils.isEmpty(displayName) || account.getAccountName().split("@")[0].equalsIgnoreCase(displayName); + if (shares.isEmpty()) { + return true; + } + + final var share = shares.get(0); + String ownerDisplayName = share.getOwnerDisplayName(); + return TextUtils.isEmpty(ownerDisplayName) || account.getAccountName().split("@")[0].equalsIgnoreCase(ownerDisplayName); } private void setShareWithYou() { if (accountOwnsFile()) { binding.sharedWithYouContainer.setVisibility(View.GONE); + } else { + if (shares.isEmpty()) { + return; + } + + final var share = shares.get(0); + + binding.sharedWithYouUsername.setText( + String.format(getString(R.string.note_share_activity_shared_with_you), share.getOwnerDisplayName())); + AvatarLoader.INSTANCE.load(this, binding.sharedWithYouAvatar, account); + binding.sharedWithYouAvatar.setVisibility(View.VISIBLE); + + String description = share.getNote(); + + if (!TextUtils.isEmpty(description)) { + binding.sharedWithYouNote.setText(description); + binding.sharedWithYouNoteContainer.setVisibility(View.VISIBLE); + } else { + binding.sharedWithYouNoteContainer.setVisibility(View.GONE); + } } } @@ -275,14 +323,14 @@ public void createPublicShareLink() { // password enforced by server, request to the user before trying to create requestPasswordForShareViaLink(true, capabilities.getAskForOptionalPassword()); } else { - executorService.schedule(() -> { + executorService.submit(() -> { final var result = repository.addShare(note, ShareType.PUBLIC_LINK, "", "false", "", 0, ""); if (result != null) { note.setIsShared(true); repository.updateNote(note); runOnUiThread(this::recreate); } - }, 0, TimeUnit.MICROSECONDS); + }); } } @@ -360,7 +408,7 @@ public void refreshCapabilitiesFromDB() { } public void refreshSharesFromDB() { - executorService.schedule(() -> { + executorService.submit(() -> { try { ShareeListAdapter adapter = (ShareeListAdapter) binding.sharesList.getAdapter(); @@ -372,8 +420,6 @@ public void refreshSharesFromDB() { adapter.getShares().clear(); // to show share with users/groups info - List shares = new ArrayList<>(); - if (note != null) { final var shareEntities = repository.getShareEntitiesForSpecificNote(note); shareEntities.forEach(entity -> { @@ -389,11 +435,12 @@ public void refreshSharesFromDB() { runOnUiThread(() -> { adapter.addShares(shares); addPublicShares(adapter); + setShareWithYou(); }); } catch (Exception e) { Log_OC.d(TAG, "Exception while refreshSharesFromDB: " + e); } - }, 0, TimeUnit.MICROSECONDS); + }); } private void addPublicShares(ShareeListAdapter adapter) { @@ -479,7 +526,8 @@ public void onSaveInstanceState(@NonNull Bundle outState) { } private boolean isReshareForbidden(OCShare share) { - return false; + return ShareType.FEDERATED == share.getShareType() || + capabilities != null && !capabilities.isReSharingAllowed(); } @VisibleForTesting @@ -501,7 +549,7 @@ public void sendNewEmail(OCShare share) { @Override public void unShare(OCShare share) { - executorService.schedule(() -> { + executorService.submit(() -> { final var result = repository.removeShare(share, note); runOnUiThread(() -> { @@ -516,7 +564,7 @@ public void unShare(OCShare share) { DisplayUtils.showSnackMessage(NoteShareActivity.this, getString(R.string.failed_the_remove_share)); } }); - }, 0, TimeUnit.MICROSECONDS); + }); } @Override diff --git a/app/src/main/java/it/niedermann/owncloud/notes/shared/model/Capabilities.java b/app/src/main/java/it/niedermann/owncloud/notes/shared/model/Capabilities.java index efb9e4918..b7a8aaed2 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/shared/model/Capabilities.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/shared/model/Capabilities.java @@ -41,6 +41,15 @@ public class Capabilities implements Serializable { private boolean publicPasswordEnforced; private boolean askForOptionalPassword; + private boolean isReSharingAllowed; + + public boolean isReSharingAllowed() { + return isReSharingAllowed; + } + + public void setReSharingAllowed(boolean value) { + this.isReSharingAllowed = value; + } public boolean getPublicPasswordEnforced() { return publicPasswordEnforced; diff --git a/app/src/main/res/layout/activity_note_share.xml b/app/src/main/res/layout/activity_note_share.xml index b4667a60b..6df68525c 100644 --- a/app/src/main/res/layout/activity_note_share.xml +++ b/app/src/main/res/layout/activity_note_share.xml @@ -77,10 +77,8 @@ app:icon="@drawable/ic_share_white_24dp" app:iconGravity="start" /> - - @@ -1198,14 +1197,6 @@ - - - - - - - - @@ -1219,14 +1210,6 @@ - - - - - - - -