Skip to content

Commit

Permalink
Merge pull request #11515 from nextcloud/tags
Browse files Browse the repository at this point in the history
Support for viewing tags
  • Loading branch information
AndyScherzinger authored May 8, 2023
2 parents 206db7c + e88ed46 commit 3e1f61a
Show file tree
Hide file tree
Showing 23 changed files with 1,393 additions and 67 deletions.
1,137 changes: 1,137 additions & 0 deletions app/schemas/com.nextcloud.client.database.NextcloudDatabase/69.json

Large diffs are not rendered by default.

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -48,27 +48,31 @@ class OCFileListFragmentStaticServerIT : AbstractIT() {
fun showFiles() {
val sut = testActivityRule.launchActivity(null)

val textFile = OCFile("/1.png")
textFile.mimeType = "image/png"
textFile.fileLength = 1024000
textFile.modificationTimestamp = 1188206955000
textFile.parentId = sut.storageManager.getFileByEncryptedRemotePath("/").fileId
sut.storageManager.saveFile(textFile)

val imageFile = OCFile("/image.png")
imageFile.mimeType = "image/png"
imageFile.isPreviewAvailable = false
imageFile.fileLength = 3072000
imageFile.modificationTimestamp = 746443755000
imageFile.parentId = sut.storageManager.getFileByEncryptedRemotePath("/").fileId
sut.storageManager.saveFile(imageFile)
OCFile("/1.png").apply {
mimeType = "image/png"
fileLength = 1024000
modificationTimestamp = 1188206955000
parentId = sut.storageManager.getFileByEncryptedRemotePath("/").fileId
sut.storageManager.saveFile(this)
}

OCFile("/image.png").apply {
mimeType = "image/png"
isPreviewAvailable = false
fileLength = 3072000
modificationTimestamp = 746443755000
parentId = sut.storageManager.getFileByEncryptedRemotePath("/").fileId
tags = listOf("Top secret")
sut.storageManager.saveFile(this)
}

OCFile("/video.mp4").apply {
mimeType = "video/mp4"
isPreviewAvailable = false
fileLength = 12092000
modificationTimestamp = 746143952000
parentId = sut.storageManager.getFileByEncryptedRemotePath("/").fileId
tags = listOf("Confidential", "+5")
sut.storageManager.saveFile(this)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,5 +117,7 @@ data class FileEntity(
@ColumnInfo(name = ProviderTableMeta.FILE_LOCK_TIMEOUT)
val lockTimeout: Int?,
@ColumnInfo(name = ProviderTableMeta.FILE_LOCK_TOKEN)
val lockToken: String?
val lockToken: String?,
@ColumnInfo(name = ProviderTableMeta.FILE_TAGS)
val tags: String?
)
Original file line number Diff line number Diff line change
Expand Up @@ -440,6 +440,7 @@ public void saveFolder(OCFile folder, List<OCFile> updatedFiles, Collection<OCFi
*/
private ContentValues createContentValuesBase(OCFile fileOrFolder) {
final ContentValues cv = new ContentValues();
final Gson gson = new Gson();
cv.put(ProviderTableMeta.FILE_MODIFIED, fileOrFolder.getModificationTimestamp());
cv.put(ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA, fileOrFolder.getModificationTimestampAtLastSyncForData());
cv.put(ProviderTableMeta.FILE_PARENT, fileOrFolder.getParentId());
Expand All @@ -464,7 +465,8 @@ private ContentValues createContentValuesBase(OCFile fileOrFolder) {
cv.put(ProviderTableMeta.FILE_OWNER_ID, fileOrFolder.getOwnerId());
cv.put(ProviderTableMeta.FILE_OWNER_DISPLAY_NAME, fileOrFolder.getOwnerDisplayName());
cv.put(ProviderTableMeta.FILE_NOTE, fileOrFolder.getNote());
cv.put(ProviderTableMeta.FILE_SHAREES, new Gson().toJson(fileOrFolder.getSharees()));
cv.put(ProviderTableMeta.FILE_SHAREES, gson.toJson(fileOrFolder.getSharees()));
cv.put(ProviderTableMeta.FILE_TAGS, gson.toJson(fileOrFolder.getTags()));
cv.put(ProviderTableMeta.FILE_RICH_WORKSPACE, fileOrFolder.getRichWorkspace());
return cv;
}
Expand Down Expand Up @@ -952,6 +954,20 @@ private OCFile createFileInstance(FileEntity fileEntity) {
}
}

String tags = fileEntity.getTags();
if (tags == null || tags.isEmpty() ||
JSON_NULL_STRING.equals(tags) || JSON_EMPTY_ARRAY.equals(tags)) {
ocFile.setTags(new ArrayList<>());
} else {
try {
String[] tagsArray = gson.fromJson(tags, String[].class);
ocFile.setTags(new ArrayList<>(Arrays.asList(tagsArray)));
} catch (JsonSyntaxException e) {
// ignore saved value due to api change
ocFile.setTags(new ArrayList<>());
}
}

String metadataSize = fileEntity.getMetadataSize();
// Surprisingly JSON deserialization causes significant overhead.
// Avoid it in common, trivial cases (null/empty).
Expand Down
10 changes: 10 additions & 0 deletions app/src/main/java/com/owncloud/android/datamodel/OCFile.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
import com.owncloud.android.utils.MimeType;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import androidx.annotation.NonNull;
Expand Down Expand Up @@ -114,6 +115,7 @@ public class OCFile implements Parcelable, Comparable<OCFile>, ServerFileInterfa
private String lockToken;
@Nullable
private ImageDimension imageDimension;
private List<String> tags = new ArrayList<>();

/**
* URI to the local path of the file contents, if stored in the device; cached after first call to {@link
Expand Down Expand Up @@ -966,4 +968,12 @@ public void setImageDimension(@Nullable ImageDimension imageDimension) {
public ImageDimension getImageDimension() {
return imageDimension;
}

public List<String> getTags() {
return tags;
}

public void setTags(List<String> tags) {
this.tags = tags;
}
}
6 changes: 4 additions & 2 deletions app/src/main/java/com/owncloud/android/db/ProviderMeta.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
*/
public class ProviderMeta {
public static final String DB_NAME = "filelist";
public static final int DB_VERSION = 68;
public static final int DB_VERSION = 69;

private ProviderMeta() {
// No instance
Expand Down Expand Up @@ -125,6 +125,7 @@ static public class ProviderTableMeta implements BaseColumns {
public static final String FILE_LOCK_TIMESTAMP = "lock_timestamp";
public static final String FILE_LOCK_TIMEOUT = "lock_timeout";
public static final String FILE_LOCK_TOKEN = "lock_token";
public static final String FILE_TAGS = "tags";

public static final List<String> FILE_ALL_COLUMNS = Collections.unmodifiableList(Arrays.asList(
_ID,
Expand Down Expand Up @@ -171,7 +172,8 @@ static public class ProviderTableMeta implements BaseColumns {
FILE_LOCK_TIMESTAMP,
FILE_LOCK_TIMEOUT,
FILE_LOCK_TOKEN,
FILE_METADATA_SIZE));
FILE_METADATA_SIZE,
FILE_TAGS));
public static final String FILE_DEFAULT_SORT_ORDER = FILE_NAME + " collate nocase asc";

// Columns of ocshares table
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@ package com.owncloud.android.ui.adapter

import android.view.View
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.TextView
import com.google.android.material.chip.ChipGroup
import com.owncloud.android.ui.AvatarGroupLayout

internal interface ListItemViewHolder : ListGridItemViewHolder {
Expand All @@ -32,4 +34,9 @@ internal interface ListItemViewHolder : ListGridItemViewHolder {
val lastModification: TextView
val overflowMenu: ImageView
val sharedAvatars: AvatarGroupLayout
val tagsGroup: ChipGroup
val firstTag: TextView
val secondTag: TextView
val tagMore: TextView
val fileDetailGroup: LinearLayout
}
Original file line number Diff line number Diff line change
Expand Up @@ -510,6 +510,7 @@ private LocalFileListItemViewHolder(View itemView) {

itemView.findViewById(R.id.sharedAvatars).setVisibility(View.GONE);
itemView.findViewById(R.id.overflow_menu).setVisibility(View.GONE);
itemView.findViewById(R.id.tagsGroup).setVisibility(View.GONE);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -418,6 +418,31 @@ private void bindListItemViewHolder(ListItemViewHolder holder, OCFile file) {
holder.getSharedAvatars().removeAllViews();
}

// tags
if (file.getTags().isEmpty()) {
holder.getTagsGroup().setVisibility(View.GONE);
holder.getFileDetailGroup().setVisibility(View.VISIBLE);
} else {
holder.getTagsGroup().setVisibility(View.VISIBLE);
holder.getFileDetailGroup().setVisibility(View.GONE);
holder.getFirstTag().setVisibility(View.VISIBLE);
holder.getSecondTag().setVisibility(View.GONE);
holder.getTagMore().setVisibility(View.GONE);

holder.getFirstTag().setText(file.getTags().get(0));

if (file.getTags().size() > 1) {
holder.getSecondTag().setVisibility(View.VISIBLE);
holder.getSecondTag().setText(file.getTags().get(1));
}

if (file.getTags().size() > 2) {
holder.getTagMore().setVisibility(View.VISIBLE);
holder.getTagMore().setText(String.format(activity.getString(R.string.tags_more),
(file.getTags().size() - 2)));
}
}

// npe fix: looks like file without local storage path somehow get here
final String storagePath = file.getStoragePath();
if (onlyOnDevice && storagePath != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,11 @@ package com.owncloud.android.ui.adapter

import android.view.View
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.elyeproj.loaderviewlibrary.LoaderImageView
import com.google.android.material.chip.ChipGroup
import com.owncloud.android.databinding.ListItemBinding
import com.owncloud.android.ui.AvatarGroupLayout

Expand All @@ -48,6 +50,16 @@ internal class OCFileListItemViewHolder(private var binding: ListItemBinding) :
get() = binding.Filename
override val thumbnail: ImageView
get() = binding.thumbnailLayout.thumbnail
override val tagsGroup: ChipGroup
get() = binding.tagsGroup
override val firstTag: TextView
get() = binding.firstTag
override val secondTag: TextView
get() = binding.secondTag
override val tagMore: TextView
get() = binding.tagMore
override val fileDetailGroup: LinearLayout
get() = binding.fileDetailGroup

override fun showVideoOverlay() {
binding.thumbnailLayout.videoOverlay.visibility = View.VISIBLE
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
package com.owncloud.android.ui.fragment;

import android.content.Context;
import android.content.res.ColorStateList;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.view.LayoutInflater;
Expand All @@ -37,6 +38,7 @@
import android.view.ViewGroup;
import android.widget.ProgressBar;

import com.google.android.material.chip.Chip;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.android.material.tabs.TabLayout;
import com.nextcloud.client.account.User;
Expand Down Expand Up @@ -226,6 +228,25 @@ public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
} else {
binding.emptyList.emptyListView.setVisibility(View.GONE);
}

Context context = getContext();
if (context == null) {
return null;
}

if (getFile().getTags().isEmpty()) {
binding.tagsGroup.setVisibility(View.GONE);
} else {
for (String tag : getFile().getTags()) {
Chip chip = new Chip(context);
chip.setText(tag);
chip.setChipBackgroundColor(ColorStateList.valueOf(getResources().getColor(R.color.bg_default,
context.getTheme())));
chip.setTextColor(getResources().getColor(R.color.list_item_lastmod_and_filesize_text,
context.getTheme()));
binding.tagsGroup.addView(chip);
}
}

return view;
}
Expand Down Expand Up @@ -316,7 +337,10 @@ public void onTabReselected(TabLayout.Tab tab) {
}
});

binding.tabLayout.getTabAt(activeTab).select();
TabLayout.Tab tab = binding.tabLayout.getTabAt(activeTab);
if (tab != null) {
tab.select();
}
}

@Override
Expand Down Expand Up @@ -559,7 +583,7 @@ private void setFilePreview(OCFile file) {
Bitmap resizedImage;

if (toolbarActivity != null && MimeTypeUtil.isImage(file)) {
String tagId = String.valueOf(ThumbnailsCacheManager.PREFIX_RESIZED_IMAGE + getFile().getRemoteId());
String tagId = ThumbnailsCacheManager.PREFIX_RESIZED_IMAGE + getFile().getRemoteId();
resizedImage = ThumbnailsCacheManager.getBitmapFromDiskCache(tagId);

if (resizedImage != null && !file.isUpdateThumbnailNeeded()) {
Expand All @@ -568,7 +592,7 @@ private void setFilePreview(OCFile file) {
} else {
// show thumbnail while loading resized image
Bitmap thumbnail = ThumbnailsCacheManager.getBitmapFromDiskCache(
String.valueOf(ThumbnailsCacheManager.PREFIX_THUMBNAIL + getFile().getRemoteId()));
ThumbnailsCacheManager.PREFIX_THUMBNAIL + getFile().getRemoteId());

if (thumbnail != null) {
toolbarActivity.setPreviewImageBitmap(thumbnail);
Expand All @@ -586,7 +610,8 @@ private void setFilePreview(OCFile file) {
containerActivity.getStorageManager(),
connectivityService,
containerActivity.getStorageManager().getUser(),
getResources().getColor(R.color.background_color_inverse)
getResources().getColor(R.color.background_color_inverse,
requireContext().getTheme())
);

if (resizedImage == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import com.owncloud.android.datamodel.OCFile;
import com.owncloud.android.lib.common.utils.Log_OC;
import com.owncloud.android.lib.resources.files.model.RemoteFile;
import com.owncloud.android.lib.resources.shares.ShareeUser;
import com.owncloud.android.ui.helpers.FileOperationsHelper;

import java.io.File;
Expand Down Expand Up @@ -233,7 +234,7 @@ public static OCFile fillOCFile(RemoteFile remote) {
file.setOwnerId(remote.getOwnerId());
file.setOwnerDisplayName(remote.getOwnerDisplayName());
file.setNote(remote.getNote());
file.setSharees(new ArrayList<>(Arrays.asList(remote.getSharees())));
file.setSharees(new ArrayList<ShareeUser>(Arrays.asList(remote.getSharees())));
file.setRichWorkspace(remote.getRichWorkspace());
file.setLocked(remote.isLocked());
file.setLockType(remote.getLockType());
Expand All @@ -243,6 +244,7 @@ public static OCFile fillOCFile(RemoteFile remote) {
file.setLockTimestamp(remote.getLockTimestamp());
file.setLockTimeout(remote.getLockTimeout());
file.setLockToken(remote.getLockToken());
file.setTags(new ArrayList<>(Arrays.asList(remote.getTags())));

return file;
}
Expand Down
6 changes: 6 additions & 0 deletions app/src/main/res/layout/file_details_fragment.xml
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,12 @@

</LinearLayout>

<com.google.android.material.chip.ChipGroup
android:id="@+id/tagsGroup"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>

</LinearLayout>

<com.google.android.material.button.MaterialButton
Expand Down
Loading

0 comments on commit 3e1f61a

Please sign in to comment.