|
1 | 1 | /* |
2 | 2 | * Nextcloud - Android Client |
3 | 3 | * |
| 4 | + * SPDX-FileCopyrightText: 2026 Alper Ozturk <alper.ozturk@nextcloud.com> |
4 | 5 | * SPDX-FileCopyrightText: 2019 Tobias Kaminsky <tobias@kaminsky.me> |
5 | 6 | * SPDX-FileCopyrightText: 2019 Nextcloud GmbH |
6 | 7 | * SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only |
7 | 8 | */ |
8 | | -package com.owncloud.android.ui.preview; |
9 | | - |
10 | | -import android.os.Bundle; |
11 | | -import android.os.Handler; |
12 | | -import android.view.LayoutInflater; |
13 | | -import android.view.Menu; |
14 | | -import android.view.MenuInflater; |
15 | | -import android.view.MenuItem; |
16 | | -import android.view.View; |
17 | | -import android.view.ViewGroup; |
18 | | - |
19 | | -import com.google.android.material.floatingactionbutton.FloatingActionButton; |
20 | | -import com.nextcloud.android.lib.richWorkspace.RichWorkspaceDirectEditingRemoteOperation; |
21 | | -import com.nextcloud.utils.extensions.FileExtensionsKt; |
22 | | -import com.owncloud.android.R; |
23 | | -import com.owncloud.android.lib.common.operations.RemoteOperationResult; |
24 | | -import com.owncloud.android.ui.activity.FileDisplayActivity; |
25 | | -import com.owncloud.android.utils.DisplayUtils; |
26 | | - |
27 | | -import androidx.annotation.NonNull; |
28 | | -import androidx.appcompat.widget.SearchView; |
29 | | -import androidx.core.view.MenuItemCompat; |
30 | | - |
31 | | -public class PreviewTextStringFragment extends PreviewTextFragment { |
32 | | - private static final String EXTRA_FILE = "FILE"; |
33 | | - |
34 | | - private final static String TAG = "PreviewTextStringFragment"; |
35 | | - private boolean isEditorWebviewLaunched = false; |
36 | | - |
37 | | - /** |
38 | | - * Creates an empty fragment for previews. |
39 | | - */ |
40 | | - public PreviewTextStringFragment() { |
41 | | - super(); |
42 | | - } |
43 | | - |
44 | | - /** |
45 | | - * {@inheritDoc} |
46 | | - */ |
47 | | - @Override |
48 | | - public void onCreate(Bundle savedInstanceState) { |
49 | | - super.onCreate(savedInstanceState); |
50 | | - |
51 | | - setHasOptionsMenu(true); |
52 | | - |
53 | | - Bundle args = getArguments(); |
54 | | - |
55 | | - if (args.containsKey(FileDisplayActivity.EXTRA_SEARCH_QUERY)) { |
56 | | - searchQuery = args.getString(FileDisplayActivity.EXTRA_SEARCH_QUERY); |
| 9 | +package com.owncloud.android.ui.preview |
| 10 | + |
| 11 | +import android.os.Bundle |
| 12 | +import android.os.Handler |
| 13 | +import android.view.LayoutInflater |
| 14 | +import android.view.Menu |
| 15 | +import android.view.MenuInflater |
| 16 | +import android.view.MenuItem |
| 17 | +import android.view.View |
| 18 | +import android.view.ViewGroup |
| 19 | +import androidx.appcompat.widget.SearchView |
| 20 | +import androidx.core.view.MenuHost |
| 21 | +import androidx.core.view.MenuProvider |
| 22 | +import androidx.lifecycle.Lifecycle |
| 23 | +import androidx.lifecycle.lifecycleScope |
| 24 | +import com.google.android.material.floatingactionbutton.FloatingActionButton |
| 25 | +import com.nextcloud.android.lib.richWorkspace.RichWorkspaceDirectEditingRemoteOperation |
| 26 | +import com.owncloud.android.R |
| 27 | +import com.owncloud.android.ui.activity.FileActivity |
| 28 | +import com.owncloud.android.ui.activity.FileDisplayActivity |
| 29 | +import com.owncloud.android.utils.DisplayUtils |
| 30 | +import kotlinx.coroutines.Dispatchers |
| 31 | +import kotlinx.coroutines.launch |
| 32 | +import kotlinx.coroutines.withContext |
| 33 | + |
| 34 | +@Suppress("TooGenericExceptionThrown") |
| 35 | +class PreviewTextStringFragment : PreviewTextFragment() { |
| 36 | + private var isEditorWebviewLaunched = false |
| 37 | + |
| 38 | + override fun onCreate(savedInstanceState: Bundle?) { |
| 39 | + super.onCreate(savedInstanceState) |
| 40 | + arguments?.run { |
| 41 | + searchQuery = getString(FileActivity.EXTRA_SEARCH_QUERY, "") |
| 42 | + searchOpen = getBoolean(FileActivity.EXTRA_SEARCH, false) |
57 | 43 | } |
58 | | - searchOpen = args.getBoolean(FileDisplayActivity.EXTRA_SEARCH, false); |
59 | | - |
60 | | - handler = new Handler(); |
| 44 | + handler = Handler() |
61 | 45 | } |
62 | 46 |
|
63 | | - /** |
64 | | - * {@inheritDoc} |
65 | | - */ |
66 | | - @Override |
67 | | - public void onSaveInstanceState(@NonNull Bundle outState) { |
68 | | - FileExtensionsKt.logFileSize(getFile(), TAG); |
69 | | - outState.putParcelable(PreviewTextStringFragment.EXTRA_FILE, getFile()); |
70 | | - |
71 | | - super.onSaveInstanceState(outState); |
| 47 | + override fun onSaveInstanceState(outState: Bundle) { |
| 48 | + outState.putParcelable(EXTRA_FILE, file) |
| 49 | + super.onSaveInstanceState(outState) |
72 | 50 | } |
73 | 51 |
|
74 | | - @Override |
75 | | - public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { |
76 | | - View view = super.onCreateView(inflater, container, savedInstanceState); |
| 52 | + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { |
| 53 | + val view = super.onCreateView(inflater, container, savedInstanceState) |
| 54 | + ?: throw RuntimeException("View can not be null") |
77 | 55 |
|
78 | | - if (view == null) { |
79 | | - throw new RuntimeException("View may not be null"); |
| 56 | + requireActivity().findViewById<FloatingActionButton>(R.id.fab_main).apply { |
| 57 | + visibility = View.VISIBLE |
| 58 | + isEnabled = true |
| 59 | + setOnClickListener { edit() } |
| 60 | + setImageResource(R.drawable.ic_edit) |
| 61 | + viewThemeUtils.material.themeFAB(this) |
80 | 62 | } |
81 | 63 |
|
82 | | - FloatingActionButton fabMain = requireActivity().findViewById(R.id.fab_main); |
83 | | - fabMain.setVisibility(View.VISIBLE); |
84 | | - fabMain.setEnabled(true); |
85 | | - fabMain.setOnClickListener(v -> edit()); |
86 | | - |
87 | | - fabMain.setImageResource(R.drawable.ic_edit); |
88 | | - viewThemeUtils.material.themeFAB(fabMain); |
89 | | - |
90 | | - return view; |
| 64 | + addMenuProvider() |
| 65 | + return view |
91 | 66 | } |
92 | 67 |
|
93 | | - @Override |
94 | | - public void onStart() { |
95 | | - if (isEditorWebviewLaunched && containerActivity instanceof FileDisplayActivity fileDisplayActivity) { |
96 | | - fileDisplayActivity.getSupportFragmentManager().popBackStack(); |
97 | | - fileDisplayActivity.onRefresh(); |
| 68 | + override fun onStart() { |
| 69 | + super.onStart() |
| 70 | + if (isEditorWebviewLaunched && containerActivity is FileDisplayActivity) { |
| 71 | + (containerActivity as FileDisplayActivity).run { |
| 72 | + supportFragmentManager.popBackStack() |
| 73 | + onRefresh() |
| 74 | + } |
98 | 75 | } |
99 | | - |
100 | | - super.onStart(); |
101 | 76 | } |
102 | 77 |
|
103 | | - /** |
104 | | - * {@inheritDoc} |
105 | | - */ |
106 | | - @Override |
107 | | - public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) { |
108 | | - super.onCreateOptionsMenu(menu, inflater); |
109 | | - |
110 | | - MenuItem menuItem = menu.findItem(R.id.action_search); |
111 | | - menuItem.setVisible(true); |
112 | | - searchView = (SearchView) MenuItemCompat.getActionView(menuItem); |
113 | | - searchView.setOnQueryTextListener(this); |
114 | | - searchView.setMaxWidth(Integer.MAX_VALUE); |
115 | | - viewThemeUtils.androidx.themeToolbarSearchView(searchView); |
116 | | - |
117 | | - if (searchOpen) { |
118 | | - searchView.setIconified(false); |
119 | | - searchView.setQuery(searchQuery, true); |
120 | | - searchView.clearFocus(); |
121 | | - } |
| 78 | + private fun addMenuProvider() { |
| 79 | + (requireActivity() as MenuHost).addMenuProvider( |
| 80 | + object : MenuProvider { |
| 81 | + override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) { |
| 82 | + menu.findItem(R.id.action_search).apply { |
| 83 | + isVisible = true |
| 84 | + searchView = (actionView as? SearchView)?.also { sv -> |
| 85 | + sv.setOnQueryTextListener(this@PreviewTextStringFragment) |
| 86 | + sv.maxWidth = Int.MAX_VALUE |
| 87 | + viewThemeUtils.androidx.themeToolbarSearchView(sv) |
| 88 | + if (searchOpen) { |
| 89 | + sv.isIconified = false |
| 90 | + sv.setQuery(searchQuery, true) |
| 91 | + sv.clearFocus() |
| 92 | + } |
| 93 | + } |
| 94 | + } |
| 95 | + } |
| 96 | + |
| 97 | + override fun onMenuItemSelected(menuItem: MenuItem) = false |
| 98 | + }, |
| 99 | + viewLifecycleOwner, |
| 100 | + Lifecycle.State.RESUMED |
| 101 | + ) |
122 | 102 | } |
123 | 103 |
|
124 | | - public void loadAndShowTextPreview() { |
125 | | - originalText = getFile().getRichWorkspace(); |
126 | | - setText(binding.textPreview, originalText, getFile(), requireActivity(), true, false, viewThemeUtils); |
127 | | - |
128 | | - binding.textPreview.setVisibility(View.VISIBLE); |
129 | | - binding.emptyListProgress.setVisibility(View.GONE); |
| 104 | + override fun loadAndShowTextPreview() { |
| 105 | + originalText = file.richWorkspace |
| 106 | + setText(binding.textPreview, originalText, file, requireActivity(), true, false, viewThemeUtils) |
| 107 | + binding.textPreview.visibility = View.VISIBLE |
| 108 | + binding.emptyListProgress.visibility = View.GONE |
130 | 109 | } |
131 | 110 |
|
132 | | - private void edit() { |
133 | | - new Thread(() -> { |
134 | | - RemoteOperationResult result = new RichWorkspaceDirectEditingRemoteOperation(getFile().getRemotePath()) |
135 | | - .execute(accountManager.getUser(), getContext()); |
136 | | - |
137 | | - if (result.isSuccess()) { |
138 | | - String url = (String) result.getSingleData(); |
139 | | - containerActivity.getFileOperationsHelper().openRichWorkspaceWithTextEditor(getFile(), |
140 | | - url, |
141 | | - getContext()); |
142 | | - isEditorWebviewLaunched = true; |
| 111 | + private fun edit() { |
| 112 | + lifecycleScope.launch(Dispatchers.IO) { |
| 113 | + val result = RichWorkspaceDirectEditingRemoteOperation(file.remotePath) |
| 114 | + .execute(accountManager.user, context) |
| 115 | + |
| 116 | + if (result.isSuccess) { |
| 117 | + containerActivity?.getFileOperationsHelper()?.openRichWorkspaceWithTextEditor( |
| 118 | + file, |
| 119 | + result.singleData as? String, |
| 120 | + context |
| 121 | + ) |
| 122 | + isEditorWebviewLaunched = true |
143 | 123 | } else { |
144 | | - DisplayUtils.showSnackMessage(getView(), "Error"); |
| 124 | + withContext(Dispatchers.Main) { |
| 125 | + activity?.let { |
| 126 | + DisplayUtils.showSnackMessage( |
| 127 | + it, |
| 128 | + R.string.preview_text_string_fragment_open_rich_text_editor_error_message |
| 129 | + ) |
| 130 | + } |
| 131 | + } |
145 | 132 | } |
146 | | - }).start(); |
| 133 | + } |
147 | 134 | } |
148 | 135 |
|
149 | | - // TODO on close clean search query |
| 136 | + companion object { |
| 137 | + private const val EXTRA_FILE = "FILE" |
| 138 | + } |
150 | 139 | } |
0 commit comments