Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature - Public Share #2575

Merged
merged 26 commits into from
Feb 18, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand All @@ -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'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
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();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
final var newNote = new Note(null, Calendar.getInstance(), NoteUtil.generateNonEmptyNoteTitle(content, this), content, categoryTitle, favorite, null, false, false);
fragment = getNewNoteFragment(newNote);
replaceFragment();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -480,7 +480,7 @@ public NotesListWidgetData getNoteListWidgetData(int appWidgetId) {
@NonNull
@MainThread
public LiveData<Note> 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);
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<Note>();
executor.submit(() -> ret.postValue(addNote(account.getId(), entity)));
return map(ret, newNote -> {
Expand Down Expand Up @@ -508,7 +508,7 @@ public Note addNote(long accountId, @NonNull Note note) {

@MainThread
public LiveData<Note> moveNoteToAnotherAccount(Account account, @NonNull Note note) {
final var fullNote = new Note(null, note.getModified(), note.getTitle(), note.getContent(), note.getCategory(), note.getFavorite(), null);
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);
Expand Down Expand Up @@ -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());
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) {
Expand All @@ -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());
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.
Expand Down Expand Up @@ -974,4 +974,8 @@ public void addShareEntities(List<ShareEntity> entities) {
public List<ShareEntity> getShareEntities(String path) {
return db.getShareDao().getShareEntities(path);
}

public void updateNote(Note note) {
db.getNoteDao().updateNote(note);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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, 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, 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, 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, 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, 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, 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, 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, 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<Note> getNoteById$(long id);
Expand Down Expand Up @@ -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 <code>null</code>
*/
@Query("SELECT id, remoteId, 0 as accountId, '' as title, 0 as favorite, '' 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<Note> getRemoteIdAndId(long accountId);

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@
@Index(name = "IDX_NOTE_ACCOUNTID", value = "accountId"),
@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")
Expand Down Expand Up @@ -81,6 +83,14 @@ public class Note implements Serializable, Item {
@ColumnInfo(defaultValue = "0")
private boolean favorite = false;

@Expose
@ColumnInfo(defaultValue = "0")
private boolean isShared = false;

@Expose
@ColumnInfo(defaultValue = "0")
private boolean readonly = false;

@Expose
@Nullable
@SerializedName("etag")
Expand All @@ -98,19 +108,20 @@ 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) {
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;
this.content = content;
this.favorite = favorite;
this.category = category;
this.eTag = eTag;
this.isShared = isShared;
}

@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) {
this(remoteId, modified, title, content, category, favorite, etag);
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;
Expand All @@ -126,6 +137,14 @@ public void setId(long id) {
this.id = id;
}

public boolean isShared() {
return isShared;
}

public void setIsShared(boolean value) {
this.isShared = value;
}

@NonNull
public String getCategory() {
return category;
Expand Down Expand Up @@ -188,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;
}
Expand Down Expand Up @@ -230,6 +257,7 @@ public boolean equals(Object o) {
if (id != note.id) return false;
if (accountId != note.accountId) return false;
if (favorite != note.favorite) return false;
if (isShared != note.isShared) return false;
if (scrollY != note.scrollY) return false;
if (!Objects.equals(remoteId, note.remoteId))
return false;
Expand All @@ -254,6 +282,7 @@ public int hashCode() {
result = 31 * result + (modified != null ? modified.hashCode() : 0);
result = 31 * result + content.hashCode();
result = 31 * result + (favorite ? 1 : 0);
result = 31 * result + (isShared ? 1 : 0);
result = 31 * result + (eTag != null ? eTag.hashCode() : 0);
result = 31 * result + excerpt.hashCode();
result = 31 * result + scrollY;
Expand All @@ -273,6 +302,7 @@ public String toString() {
", modified=" + modified +
", content='" + content + '\'' +
", favorite=" + favorite +
", isShared=" + isShared +
", eTag='" + eTag + '\'' +
", excerpt='" + excerpt + '\'' +
", scrollY=" + scrollY +
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,5 @@ data class ShareEntity(
val displayname_file_owner: String? = null,
val uid_owner: String? = null,
val displayname_owner: String? = null,
val url: String? = null
)
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,16 @@ public Capabilities deserialize(JsonElement json, Type typeOfT, JsonDeserializat
final var outgoing = federation.get("outgoing");

response.setFederationShare(outgoing.getAsBoolean());

final var publicObject = filesSharing.getAsJsonObject("public");
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)) {
Expand Down
Loading
Loading