Loading app/src/main/java/it/niedermann/owncloud/notes/persistence/ShareRepository.kt +63 −7 Original line number Diff line number Diff line Loading @@ -2,18 +2,18 @@ package it.niedermann.owncloud.notes.persistence import android.app.Application import android.content.Context import android.util.Log import com.nextcloud.android.sso.api.EmptyResponse import com.nextcloud.android.sso.model.SingleSignOnAccount import com.owncloud.android.lib.common.utils.Log_OC import com.owncloud.android.lib.resources.shares.GetShareesRemoteOperation import com.owncloud.android.lib.resources.shares.OCShare import com.owncloud.android.lib.resources.shares.ShareType import io.reactivex.Single import io.reactivex.schedulers.Schedulers import it.niedermann.owncloud.notes.persistence.entity.Note import it.niedermann.owncloud.notes.share.model.ShareesData import it.niedermann.owncloud.notes.shared.model.ApiVersion import org.json.JSONArray import org.json.JSONObject import java.util.ArrayList class ShareRepository private constructor(private val applicationContext: Context) { Loading @@ -37,15 +37,71 @@ class ShareRepository private constructor(private val applicationContext: Contex searchString: String, page: Int, perPage: Int ): Single<ShareesData> { ): Single<ArrayList<JSONObject>> { return Single.fromCallable { val shareAPI = apiProvider.getShareAPI(applicationContext, account) val call2 = shareAPI.getSharees2(search = searchString, page = page, perPage = perPage) val response2 = call2.execute() val call = shareAPI.getSharees(search = searchString, page = page, perPage = perPage) val response = call.execute() response.body()?.ocs?.data ?: throw RuntimeException("No shares available") val respJSON = JSONObject(response2.body().toString()) val respOCS = respJSON.getJSONObject("ocs") val respData = respOCS.getJSONObject("data") val respExact = respData.getJSONObject("exact") val respExactUsers = respExact.getJSONArray("users") val respExactGroups = respExact.getJSONArray("groups") val respExactRemotes = respExact.getJSONArray("remotes") val respExactCircles = if (respExact.has("circles")) { respExact.getJSONArray("circles") } else { JSONArray() } val respExactRooms = if (respExact.has("rooms")) { respExact.getJSONArray("rooms") } else { JSONArray() } val respExactEmails = respExact.getJSONArray("emails") val respPartialUsers = respData.getJSONArray("users") val respPartialGroups = respData.getJSONArray("groups") val respPartialRemotes = respData.getJSONArray("remotes") val respPartialCircles = if (respData.has("circles")) { respData.getJSONArray("circles") } else { JSONArray() } val respPartialRooms = if (respData.has("rooms")) { respData.getJSONArray("rooms") } else { JSONArray() } val jsonResults = arrayOf( respExactUsers, respExactGroups, respExactRemotes, respExactRooms, respExactEmails, respExactCircles, respPartialUsers, respPartialGroups, respPartialRemotes, respPartialRooms, respPartialCircles ) val data: ArrayList<JSONObject> = ArrayList() val var25 = jsonResults val var26 = jsonResults.size for (var27 in 0 until var26) { val jsonResult = var25[var27] for (j in 0 until jsonResult.length()) { val jsonObject = jsonResult.getJSONObject(j) data.add(jsonObject) } } data }.subscribeOn(Schedulers.io()) } Loading app/src/main/java/it/niedermann/owncloud/notes/persistence/sync/ShareAPI.kt +2 −2 Original line number Diff line number Diff line Loading @@ -16,7 +16,7 @@ interface ShareAPI { @GET("sharees") fun getSharees2( @Query("format") format: String = "json", @Query("itemType") itemType: String = "note", @Query("itemType") itemType: String = "file", @Query("search") search: String, @Query("page") page: Int, @Query("perPage") perPage: Int, Loading @@ -26,7 +26,7 @@ interface ShareAPI { @GET("sharees") fun getSharees( @Query("format") format: String = "json", @Query("itemType") itemType: String = "note", @Query("itemType") itemType: String = "file", @Query("search") search: String, @Query("page") page: Int, @Query("perPage") perPage: Int, Loading app/src/main/java/it/niedermann/owncloud/notes/share/helper/UsersAndGroupsSearchProvider.java +131 −1 Original line number Diff line number Diff line Loading @@ -130,7 +130,137 @@ public class UsersAndGroupsSearchProvider { final SingleSignOnAccount ssoAcc; try { ssoAcc = SingleAccountHelper.getCurrentSingleSignOnAccount(context); return repository.getSharees(ssoAcc, userQuery, REQUESTED_PAGE, RESULTS_PER_PAGE).blockingGet(); final var names = repository.getSharees(ssoAcc, userQuery, REQUESTED_PAGE, RESULTS_PER_PAGE).blockingGet(); ShareesData data = new ShareesData(null,null,null ); if (!names.isEmpty()) { MatrixCursor response = new MatrixCursor(COLUMNS); Uri userBaseUri = new Uri.Builder().scheme(CONTENT).authority(DATA_USER).build(); Uri groupBaseUri = new Uri.Builder().scheme(CONTENT).authority(DATA_GROUP).build(); Uri roomBaseUri = new Uri.Builder().scheme(CONTENT).authority(DATA_ROOM).build(); Uri remoteBaseUri = new Uri.Builder().scheme(CONTENT).authority(DATA_REMOTE).build(); Uri emailBaseUri = new Uri.Builder().scheme(CONTENT).authority(DATA_EMAIL).build(); Uri circleBaseUri = new Uri.Builder().scheme(CONTENT).authority(DATA_CIRCLE).build(); Iterator<JSONObject> namesIt = names.iterator(); JSONObject item; String displayName; String subline = null; Object icon = 0; Uri dataUri; int count = 0; while (namesIt.hasNext()) { item = namesIt.next(); dataUri = null; displayName = null; String userName = item.getString(GetShareesRemoteOperation.PROPERTY_LABEL); String name = item.isNull("name") ? "" : item.getString("name"); JSONObject value = item.getJSONObject(GetShareesRemoteOperation.NODE_VALUE); ShareType type = ShareType.fromValue(value.getInt(GetShareesRemoteOperation.PROPERTY_SHARE_TYPE)); String shareWith = value.getString(GetShareesRemoteOperation.PROPERTY_SHARE_WITH); Status status; JSONObject statusObject = item.optJSONObject(PROPERTY_STATUS); if (statusObject != null) { status = new Status( StatusType.valueOf(statusObject.getString(PROPERTY_STATUS).toUpperCase(Locale.US)), statusObject.isNull(PROPERTY_MESSAGE) ? "" : statusObject.getString(PROPERTY_MESSAGE), statusObject.isNull(PROPERTY_ICON) ? "" : statusObject.getString(PROPERTY_ICON), statusObject.isNull(PROPERTY_CLEAR_AT) ? -1 : statusObject.getLong(PROPERTY_CLEAR_AT)); } else { status = new Status(StatusType.OFFLINE, "", "", -1); } if (UsersAndGroupsSearchConfig.INSTANCE.getSearchOnlyUsers() && type != ShareType.USER) { // skip all types but users, as E2E secure share is only allowed to users on same server // TODO: CHECK SKIP LOGIC // continue; } switch (type) { case GROUP: displayName = userName; icon = R.drawable.ic_group; dataUri = Uri.withAppendedPath(groupBaseUri, shareWith); break; case FEDERATED: // TODO: federatedShareAllowed if (true) { icon = R.drawable.ic_account_circle_grey_24dp; dataUri = Uri.withAppendedPath(remoteBaseUri, shareWith); if (userName.equals(shareWith)) { displayName = name; subline = context.getString(R.string.remote); } else { String[] uriSplitted = shareWith.split("@"); displayName = name; subline = context.getString(R.string.share_known_remote_on_clarification, uriSplitted[uriSplitted.length - 1]); } } break; case USER: displayName = userName; subline = (status.getMessage() == null || status.getMessage().isEmpty()) ? null : status.getMessage(); Uri.Builder builder = Uri.parse("content://" + AUTHORITY + "/icon").buildUpon(); builder.appendQueryParameter("shareWith", shareWith); builder.appendQueryParameter("displayName", displayName); builder.appendQueryParameter("status", status.getStatus().toString()); if (!TextUtils.isEmpty(status.getIcon()) && !"null".equals(status.getIcon())) { builder.appendQueryParameter("icon", status.getIcon()); } icon = builder.build(); dataUri = Uri.withAppendedPath(userBaseUri, shareWith); break; case EMAIL: icon = R.drawable.ic_email; displayName = name; subline = shareWith; dataUri = Uri.withAppendedPath(emailBaseUri, shareWith); break; case ROOM: icon = R.drawable.ic_talk; displayName = userName; dataUri = Uri.withAppendedPath(roomBaseUri, shareWith); break; case CIRCLE: icon = R.drawable.ic_circles; displayName = userName; dataUri = Uri.withAppendedPath(circleBaseUri, shareWith); break; default: break; } if (displayName != null && dataUri != null) { response.newRow() .add(count++) // BaseColumns._ID .add(displayName) // SearchManager.SUGGEST_COLUMN_TEXT_1 .add(subline) // SearchManager.SUGGEST_COLUMN_TEXT_2 .add(icon) // SearchManager.SUGGEST_COLUMN_ICON_1 .add(dataUri); } data.setDisplayName(displayName); data.setDataUri(dataUri); data.setIcon(icon); } } return data; } catch (Exception e) { Log_OC.e(TAG, "Exception while searching", e); } Loading app/src/main/java/it/niedermann/owncloud/notes/share/model/ShareesData.kt +5 −29 Original line number Diff line number Diff line package it.niedermann.owncloud.notes.share.model data class ShareesData( val exact: ExactMatches, val users: List<ShareeItem>, val groups: List<ShareeItem>, val remotes: List<ShareeItem>, val remote_groups: List<ShareeItem>, val emails: List<ShareeItem>, val circles: List<ShareeItem>, val rooms: List<ShareeItem>, val lookup: List<ShareeItem>, val lookupEnabled: Boolean ) data class ExactMatches( val users: List<ShareeItem>, val groups: List<ShareeItem>, val remotes: List<ShareeItem>, val remote_groups: List<ShareeItem>, val emails: List<ShareeItem>, val circles: List<ShareeItem>, val rooms: List<ShareeItem> ) import android.net.Uri data class ShareeItem( val label: String, val value: ShareeValue data class ShareesData( var displayName: String?, var dataUri: Uri?, var icon: Any?, ) data class ShareeValue( val shareType: Double, val shareWith: String ) Loading
app/src/main/java/it/niedermann/owncloud/notes/persistence/ShareRepository.kt +63 −7 Original line number Diff line number Diff line Loading @@ -2,18 +2,18 @@ package it.niedermann.owncloud.notes.persistence import android.app.Application import android.content.Context import android.util.Log import com.nextcloud.android.sso.api.EmptyResponse import com.nextcloud.android.sso.model.SingleSignOnAccount import com.owncloud.android.lib.common.utils.Log_OC import com.owncloud.android.lib.resources.shares.GetShareesRemoteOperation import com.owncloud.android.lib.resources.shares.OCShare import com.owncloud.android.lib.resources.shares.ShareType import io.reactivex.Single import io.reactivex.schedulers.Schedulers import it.niedermann.owncloud.notes.persistence.entity.Note import it.niedermann.owncloud.notes.share.model.ShareesData import it.niedermann.owncloud.notes.shared.model.ApiVersion import org.json.JSONArray import org.json.JSONObject import java.util.ArrayList class ShareRepository private constructor(private val applicationContext: Context) { Loading @@ -37,15 +37,71 @@ class ShareRepository private constructor(private val applicationContext: Contex searchString: String, page: Int, perPage: Int ): Single<ShareesData> { ): Single<ArrayList<JSONObject>> { return Single.fromCallable { val shareAPI = apiProvider.getShareAPI(applicationContext, account) val call2 = shareAPI.getSharees2(search = searchString, page = page, perPage = perPage) val response2 = call2.execute() val call = shareAPI.getSharees(search = searchString, page = page, perPage = perPage) val response = call.execute() response.body()?.ocs?.data ?: throw RuntimeException("No shares available") val respJSON = JSONObject(response2.body().toString()) val respOCS = respJSON.getJSONObject("ocs") val respData = respOCS.getJSONObject("data") val respExact = respData.getJSONObject("exact") val respExactUsers = respExact.getJSONArray("users") val respExactGroups = respExact.getJSONArray("groups") val respExactRemotes = respExact.getJSONArray("remotes") val respExactCircles = if (respExact.has("circles")) { respExact.getJSONArray("circles") } else { JSONArray() } val respExactRooms = if (respExact.has("rooms")) { respExact.getJSONArray("rooms") } else { JSONArray() } val respExactEmails = respExact.getJSONArray("emails") val respPartialUsers = respData.getJSONArray("users") val respPartialGroups = respData.getJSONArray("groups") val respPartialRemotes = respData.getJSONArray("remotes") val respPartialCircles = if (respData.has("circles")) { respData.getJSONArray("circles") } else { JSONArray() } val respPartialRooms = if (respData.has("rooms")) { respData.getJSONArray("rooms") } else { JSONArray() } val jsonResults = arrayOf( respExactUsers, respExactGroups, respExactRemotes, respExactRooms, respExactEmails, respExactCircles, respPartialUsers, respPartialGroups, respPartialRemotes, respPartialRooms, respPartialCircles ) val data: ArrayList<JSONObject> = ArrayList() val var25 = jsonResults val var26 = jsonResults.size for (var27 in 0 until var26) { val jsonResult = var25[var27] for (j in 0 until jsonResult.length()) { val jsonObject = jsonResult.getJSONObject(j) data.add(jsonObject) } } data }.subscribeOn(Schedulers.io()) } Loading
app/src/main/java/it/niedermann/owncloud/notes/persistence/sync/ShareAPI.kt +2 −2 Original line number Diff line number Diff line Loading @@ -16,7 +16,7 @@ interface ShareAPI { @GET("sharees") fun getSharees2( @Query("format") format: String = "json", @Query("itemType") itemType: String = "note", @Query("itemType") itemType: String = "file", @Query("search") search: String, @Query("page") page: Int, @Query("perPage") perPage: Int, Loading @@ -26,7 +26,7 @@ interface ShareAPI { @GET("sharees") fun getSharees( @Query("format") format: String = "json", @Query("itemType") itemType: String = "note", @Query("itemType") itemType: String = "file", @Query("search") search: String, @Query("page") page: Int, @Query("perPage") perPage: Int, Loading
app/src/main/java/it/niedermann/owncloud/notes/share/helper/UsersAndGroupsSearchProvider.java +131 −1 Original line number Diff line number Diff line Loading @@ -130,7 +130,137 @@ public class UsersAndGroupsSearchProvider { final SingleSignOnAccount ssoAcc; try { ssoAcc = SingleAccountHelper.getCurrentSingleSignOnAccount(context); return repository.getSharees(ssoAcc, userQuery, REQUESTED_PAGE, RESULTS_PER_PAGE).blockingGet(); final var names = repository.getSharees(ssoAcc, userQuery, REQUESTED_PAGE, RESULTS_PER_PAGE).blockingGet(); ShareesData data = new ShareesData(null,null,null ); if (!names.isEmpty()) { MatrixCursor response = new MatrixCursor(COLUMNS); Uri userBaseUri = new Uri.Builder().scheme(CONTENT).authority(DATA_USER).build(); Uri groupBaseUri = new Uri.Builder().scheme(CONTENT).authority(DATA_GROUP).build(); Uri roomBaseUri = new Uri.Builder().scheme(CONTENT).authority(DATA_ROOM).build(); Uri remoteBaseUri = new Uri.Builder().scheme(CONTENT).authority(DATA_REMOTE).build(); Uri emailBaseUri = new Uri.Builder().scheme(CONTENT).authority(DATA_EMAIL).build(); Uri circleBaseUri = new Uri.Builder().scheme(CONTENT).authority(DATA_CIRCLE).build(); Iterator<JSONObject> namesIt = names.iterator(); JSONObject item; String displayName; String subline = null; Object icon = 0; Uri dataUri; int count = 0; while (namesIt.hasNext()) { item = namesIt.next(); dataUri = null; displayName = null; String userName = item.getString(GetShareesRemoteOperation.PROPERTY_LABEL); String name = item.isNull("name") ? "" : item.getString("name"); JSONObject value = item.getJSONObject(GetShareesRemoteOperation.NODE_VALUE); ShareType type = ShareType.fromValue(value.getInt(GetShareesRemoteOperation.PROPERTY_SHARE_TYPE)); String shareWith = value.getString(GetShareesRemoteOperation.PROPERTY_SHARE_WITH); Status status; JSONObject statusObject = item.optJSONObject(PROPERTY_STATUS); if (statusObject != null) { status = new Status( StatusType.valueOf(statusObject.getString(PROPERTY_STATUS).toUpperCase(Locale.US)), statusObject.isNull(PROPERTY_MESSAGE) ? "" : statusObject.getString(PROPERTY_MESSAGE), statusObject.isNull(PROPERTY_ICON) ? "" : statusObject.getString(PROPERTY_ICON), statusObject.isNull(PROPERTY_CLEAR_AT) ? -1 : statusObject.getLong(PROPERTY_CLEAR_AT)); } else { status = new Status(StatusType.OFFLINE, "", "", -1); } if (UsersAndGroupsSearchConfig.INSTANCE.getSearchOnlyUsers() && type != ShareType.USER) { // skip all types but users, as E2E secure share is only allowed to users on same server // TODO: CHECK SKIP LOGIC // continue; } switch (type) { case GROUP: displayName = userName; icon = R.drawable.ic_group; dataUri = Uri.withAppendedPath(groupBaseUri, shareWith); break; case FEDERATED: // TODO: federatedShareAllowed if (true) { icon = R.drawable.ic_account_circle_grey_24dp; dataUri = Uri.withAppendedPath(remoteBaseUri, shareWith); if (userName.equals(shareWith)) { displayName = name; subline = context.getString(R.string.remote); } else { String[] uriSplitted = shareWith.split("@"); displayName = name; subline = context.getString(R.string.share_known_remote_on_clarification, uriSplitted[uriSplitted.length - 1]); } } break; case USER: displayName = userName; subline = (status.getMessage() == null || status.getMessage().isEmpty()) ? null : status.getMessage(); Uri.Builder builder = Uri.parse("content://" + AUTHORITY + "/icon").buildUpon(); builder.appendQueryParameter("shareWith", shareWith); builder.appendQueryParameter("displayName", displayName); builder.appendQueryParameter("status", status.getStatus().toString()); if (!TextUtils.isEmpty(status.getIcon()) && !"null".equals(status.getIcon())) { builder.appendQueryParameter("icon", status.getIcon()); } icon = builder.build(); dataUri = Uri.withAppendedPath(userBaseUri, shareWith); break; case EMAIL: icon = R.drawable.ic_email; displayName = name; subline = shareWith; dataUri = Uri.withAppendedPath(emailBaseUri, shareWith); break; case ROOM: icon = R.drawable.ic_talk; displayName = userName; dataUri = Uri.withAppendedPath(roomBaseUri, shareWith); break; case CIRCLE: icon = R.drawable.ic_circles; displayName = userName; dataUri = Uri.withAppendedPath(circleBaseUri, shareWith); break; default: break; } if (displayName != null && dataUri != null) { response.newRow() .add(count++) // BaseColumns._ID .add(displayName) // SearchManager.SUGGEST_COLUMN_TEXT_1 .add(subline) // SearchManager.SUGGEST_COLUMN_TEXT_2 .add(icon) // SearchManager.SUGGEST_COLUMN_ICON_1 .add(dataUri); } data.setDisplayName(displayName); data.setDataUri(dataUri); data.setIcon(icon); } } return data; } catch (Exception e) { Log_OC.e(TAG, "Exception while searching", e); } Loading
app/src/main/java/it/niedermann/owncloud/notes/share/model/ShareesData.kt +5 −29 Original line number Diff line number Diff line package it.niedermann.owncloud.notes.share.model data class ShareesData( val exact: ExactMatches, val users: List<ShareeItem>, val groups: List<ShareeItem>, val remotes: List<ShareeItem>, val remote_groups: List<ShareeItem>, val emails: List<ShareeItem>, val circles: List<ShareeItem>, val rooms: List<ShareeItem>, val lookup: List<ShareeItem>, val lookupEnabled: Boolean ) data class ExactMatches( val users: List<ShareeItem>, val groups: List<ShareeItem>, val remotes: List<ShareeItem>, val remote_groups: List<ShareeItem>, val emails: List<ShareeItem>, val circles: List<ShareeItem>, val rooms: List<ShareeItem> ) import android.net.Uri data class ShareeItem( val label: String, val value: ShareeValue data class ShareesData( var displayName: String?, var dataUri: Uri?, var icon: Any?, ) data class ShareeValue( val shareType: Double, val shareWith: String )