Skip to content
This repository was archived by the owner on Dec 3, 2024. It is now read-only.

Commit ae1a93e

Browse files
committed
move override changes button to folder settings with clear description and confirmation, while attempting to largely match existing verbiage and iconography in web gui
1 parent d415716 commit ae1a93e

File tree

9 files changed

+150
-40
lines changed

9 files changed

+150
-40
lines changed

app/src/main/java/com/nutomic/syncthingandroid/activities/DeviceActivity.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ public class DeviceActivity extends SyncthingActivity implements View.OnClickLis
5757
private static final String TAG = "DeviceSettingsFragment";
5858
private static final String IS_SHOWING_DISCARD_DIALOG = "DISCARD_FOLDER_DIALOG_STATE";
5959
private static final String IS_SHOWING_COMPRESSION_DIALOG = "COMPRESSION_FOLDER_DIALOG_STATE";
60-
private static final String IS_SHOWING_DELETE_DIALOG = "DELETE_FOLDER_DIALOG_STATE";
60+
private static final String IS_SHOW_DELETE_DIALOG = "DELETE_FOLDER_DIALOG_STATE";
6161
private static final int QR_SCAN_REQUEST_CODE = 777;
6262

6363
private static final List<String> DYNAMIC_ADDRESS = Collections.singletonList("dynamic");
@@ -170,7 +170,7 @@ private void restoreDialogStates(Bundle savedInstanceState) {
170170
showCompressionDialog();
171171
}
172172

173-
if (savedInstanceState.getBoolean(IS_SHOWING_DELETE_DIALOG)){
173+
if (savedInstanceState.getBoolean(IS_SHOW_DELETE_DIALOG)){
174174
showDeleteDialog();
175175
}
176176

@@ -220,7 +220,7 @@ public void onSaveInstanceState(Bundle outState) {
220220
outState.putBoolean(IS_SHOWING_COMPRESSION_DIALOG, mCompressionDialog != null && mCompressionDialog.isShowing());
221221
Util.dismissDialogSafe(mCompressionDialog, this);
222222

223-
outState.putBoolean(IS_SHOWING_DELETE_DIALOG, mDeleteDialog != null && mDeleteDialog.isShowing());
223+
outState.putBoolean(IS_SHOW_DELETE_DIALOG, mDeleteDialog != null && mDeleteDialog.isShowing());
224224
Util.dismissDialogSafe(mDeleteDialog, this);
225225
}
226226

app/src/main/java/com/nutomic/syncthingandroid/activities/FolderActivity.java

+60-4
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import com.nutomic.syncthingandroid.databinding.FragmentFolderBinding;
3131
import com.nutomic.syncthingandroid.model.Device;
3232
import com.nutomic.syncthingandroid.model.Folder;
33+
import com.nutomic.syncthingandroid.model.FolderStatus;
3334
import com.nutomic.syncthingandroid.service.Constants;
3435
import com.nutomic.syncthingandroid.service.RestApi;
3536
import com.nutomic.syncthingandroid.service.SyncthingService;
@@ -65,13 +66,16 @@ public class FolderActivity extends SyncthingActivity
6566
"com.nutomic.syncthingandroid.activities.FolderActivity.FOLDER_ID";
6667
public static final String EXTRA_FOLDER_LABEL =
6768
"com.nutomic.syncthingandroid.activities.FolderActivity.FOLDER_LABEL";
69+
public static final String EXTRA_FOLDER_OVERRIDABLE_CHANGES =
70+
"com.nutomic.syncthingandroid.activities.FolderActivity.FOLDER_OVERRIDABLE_CHANGES";
6871
public static final String EXTRA_DEVICE_ID =
6972
"com.nutomic.syncthingandroid.activities.FolderActivity.DEVICE_ID";
7073

7174
private static final String TAG = "FolderActivity";
7275

73-
private static final String IS_SHOWING_DELETE_DIALOG = "DELETE_FOLDER_DIALOG_STATE";
76+
private static final String IS_SHOW_DELETE_DIALOG = "DELETE_FOLDER_DIALOG_STATE";
7477
private static final String IS_SHOW_DISCARD_DIALOG = "DISCARD_FOLDER_DIALOG_STATE";
78+
private static final String IS_SHOW_OVERRIDE_CHANGES_DIALOG = "OVERRIDE_REMOTES_DIALOG_STATE";
7579

7680
private static final int FILE_VERSIONING_DIALOG_REQUEST = 3454;
7781
private static final int PULL_ORDER_DIALOG_REQUEST = 3455;
@@ -93,6 +97,7 @@ public class FolderActivity extends SyncthingActivity
9397

9498
private Dialog mDeleteDialog;
9599
private Dialog mDiscardDialog;
100+
private Dialog mOverrideChangesDialog;
96101

97102
private Folder.Versioning mVersioning;
98103

@@ -148,6 +153,7 @@ public void onCreate(Bundle savedInstanceState) {
148153
findViewById(R.id.pullOrderContainer).setOnClickListener(v -> showPullOrderDialog());
149154
findViewById(R.id.versioningContainer).setOnClickListener(v -> showVersioningDialog());
150155
binding.editIgnores.setOnClickListener(v -> editIgnores());
156+
binding.overrideChangesContainer.setOnClickListener(v -> showOverrideChangesDialog());
151157

152158
if (mIsCreateMode) {
153159
if (savedInstanceState != null) {
@@ -162,26 +168,40 @@ public void onCreate(Bundle savedInstanceState) {
162168
// Open keyboard on label view in edit mode.
163169
binding.label.requestFocus();
164170
binding.editIgnores.setEnabled(false);
171+
setOverrideChangesContainerEnabled(false);
165172
}
166173
else {
167174
// Prepare edit mode.
168175
binding.id.clearFocus();
169176
binding.id.setFocusable(false);
170177
binding.id.setEnabled(false);
171178
binding.directoryTextView.setEnabled(false);
179+
180+
// overridable remotes button
181+
setOverrideChangesContainerEnabled(
182+
getIntent().hasExtra(EXTRA_FOLDER_OVERRIDABLE_CHANGES)
183+
&& getIntent().getBooleanExtra(EXTRA_FOLDER_OVERRIDABLE_CHANGES, false)
184+
);
172185
}
173186

174187
if (savedInstanceState != null){
175-
if (savedInstanceState.getBoolean(IS_SHOWING_DELETE_DIALOG)){
188+
if (savedInstanceState.getBoolean(IS_SHOW_DELETE_DIALOG)){
176189
showDeleteDialog();
177190
}
178191
}
179192

180193
if (savedInstanceState != null){
181-
if (savedInstanceState.getBoolean(IS_SHOWING_DELETE_DIALOG)){
194+
if (savedInstanceState.getBoolean(IS_SHOW_DELETE_DIALOG)){
182195
showDeleteDialog();
183196
}
184197
}
198+
199+
if (savedInstanceState != null) {
200+
if (savedInstanceState.getBoolean(IS_SHOW_OVERRIDE_CHANGES_DIALOG)){
201+
showOverrideChangesDialog();
202+
}
203+
}
204+
185205
}
186206

187207
/**
@@ -304,12 +324,18 @@ public void onPause() {
304324
@Override
305325
protected void onSaveInstanceState(Bundle outState) {
306326
super.onSaveInstanceState(outState);
307-
outState.putBoolean(IS_SHOWING_DELETE_DIALOG, mDeleteDialog != null && mDeleteDialog.isShowing());
327+
outState.putBoolean(IS_SHOW_DELETE_DIALOG, mDeleteDialog != null && mDeleteDialog.isShowing());
308328
Util.dismissDialogSafe(mDeleteDialog, this);
309329

330+
outState.putBoolean(IS_SHOW_OVERRIDE_CHANGES_DIALOG, mOverrideChangesDialog != null && mOverrideChangesDialog.isShowing());
331+
Util.dismissDialogSafe(mOverrideChangesDialog, this);
332+
310333
if (mIsCreateMode){
311334
outState.putBoolean(IS_SHOW_DISCARD_DIALOG, mDiscardDialog != null && mDiscardDialog.isShowing());
312335
Util.dismissDialogSafe(mDiscardDialog, this);
336+
337+
outState.putBoolean(IS_SHOW_OVERRIDE_CHANGES_DIALOG, mOverrideChangesDialog != null && mOverrideChangesDialog.isShowing());
338+
Util.dismissDialogSafe(mOverrideChangesDialog, this);
313339
}
314340
}
315341

@@ -778,4 +804,34 @@ private void setVersioningDescription(String type, String description) {
778804
binding.versioningType.setText(type);
779805
binding.versioningDescription.setText(description);
780806
}
807+
808+
private void setOverrideChangesContainerEnabled(boolean state) {
809+
LinearLayout container = (LinearLayout) findViewById(R.id.overrideChangesContainer);
810+
binding.overrideChangesContainer.setEnabled(state);
811+
for ( int i = 0; i < container.getChildCount(); i++ ) {
812+
container.getChildAt(i).setEnabled(state);
813+
}
814+
}
815+
816+
private void showOverrideChangesDialog(){
817+
mOverrideChangesDialog = createOverrideChangesDialog();
818+
mOverrideChangesDialog.show();
819+
}
820+
821+
private Dialog createOverrideChangesDialog(){
822+
return Util.getAlertDialogBuilder(this)
823+
.setIcon(R.drawable.outline_arrow_circle_up_24)
824+
.setTitle(R.string.override_changes)
825+
.setMessage(R.string.override_changes_are_you_sure)
826+
.setNegativeButton(android.R.string.cancel, null)
827+
.setPositiveButton(android.R.string.yes, (dialogInterface, i) -> {
828+
RestApi restApi = getApi();
829+
if (restApi != null) {
830+
restApi.overrideChanges(mFolder.id);
831+
mFolderNeedsToUpdate = true;
832+
}
833+
finish();
834+
})
835+
.create();
836+
}
781837
}

app/src/main/java/com/nutomic/syncthingandroid/fragments/FolderListFragment.java

+8-1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import com.nutomic.syncthingandroid.activities.FolderActivity;
1414
import com.nutomic.syncthingandroid.activities.SyncthingActivity;
1515
import com.nutomic.syncthingandroid.model.Folder;
16+
import com.nutomic.syncthingandroid.model.FolderStatus;
1617
import com.nutomic.syncthingandroid.service.Constants;
1718
import com.nutomic.syncthingandroid.service.RestApi;
1819
import com.nutomic.syncthingandroid.service.SyncthingService;
@@ -101,9 +102,15 @@ private void updateList() {
101102

102103
@Override
103104
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
105+
Folder folder = mAdapter.getItem(i);
106+
FolderStatus folderStatus = mAdapter.mLocalFolderStatuses.get(folder.id);
107+
boolean overridableChanges = folder.type.equals(Constants.FOLDER_TYPE_SEND_ONLY)
108+
&& folderStatus.isNeedsItems()
109+
&& folderStatus.isOutOfSync();
104110
Intent intent = new Intent(getActivity(), FolderActivity.class)
105111
.putExtra(FolderActivity.EXTRA_IS_CREATE, false)
106-
.putExtra(FolderActivity.EXTRA_FOLDER_ID, mAdapter.getItem(i).id);
112+
.putExtra(FolderActivity.EXTRA_FOLDER_ID, mAdapter.getItem(i).id)
113+
.putExtra(FolderActivity.EXTRA_FOLDER_OVERRIDABLE_CHANGES, overridableChanges);
107114
startActivity(intent);
108115
}
109116

app/src/main/java/com/nutomic/syncthingandroid/model/FolderStatus.java

+8
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,12 @@ public class FolderStatus {
2727
public long version;
2828
public String error;
2929
public String watchError;
30+
31+
public boolean isNeedsItems() {
32+
return needFiles + needDirectories + needSymlinks + needDeletes > 0;
33+
}
34+
35+
public boolean isOutOfSync() {
36+
return state.equals("idle") && isNeedsItems();
37+
}
3038
}

app/src/main/java/com/nutomic/syncthingandroid/views/FoldersAdapter.java

+2-15
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ public class FoldersAdapter extends ArrayAdapter<Folder> {
4040

4141
private static final String TAG = "FoldersAdapter";
4242

43-
private final HashMap<String, FolderStatus> mLocalFolderStatuses = new HashMap<>();
43+
public final HashMap<String, FolderStatus> mLocalFolderStatuses = new HashMap<>();
4444

4545
private final Context mContext;
4646

@@ -59,13 +59,6 @@ public View getView(int position, View convertView, @NonNull ViewGroup parent) {
5959
Folder folder = getItem(position);
6060
binding.label.setText(TextUtils.isEmpty(folder.label) ? folder.id : folder.label);
6161
binding.directory.setText(folder.path);
62-
binding.override.setOnClickListener(v -> {
63-
// Send "Override changes" through our service to the REST API.
64-
Intent intent = new Intent(mContext, SyncthingService.class)
65-
.putExtra(SyncthingService.EXTRA_FOLDER_ID, folder.id);
66-
intent.setAction(SyncthingService.ACTION_OVERRIDE_CHANGES);
67-
mContext.startService(intent);
68-
});
6962
binding.openFolder.setOnClickListener(v -> {
7063
Intent intent = new Intent(Intent.ACTION_VIEW);
7164
intent.setDataAndType(Uri.fromFile(new File(folder.path)), "resource/folder");
@@ -94,17 +87,12 @@ private void updateFolderStatusView(ItemFolderListBinding binding, Folder folder
9487
FolderStatus folderStatus = mLocalFolderStatuses.get(folder.id);
9588
if (folderStatus == null) {
9689
binding.items.setVisibility(GONE);
97-
binding.override.setVisibility(GONE);
9890
binding.size.setVisibility(GONE);
9991
setTextOrHide(binding.invalid, folder.invalid);
10092
return;
10193
}
10294

103-
long neededItems = folderStatus.needFiles + folderStatus.needDirectories + folderStatus.needSymlinks + folderStatus.needDeletes;
104-
boolean outOfSync = folderStatus.state.equals("idle") && neededItems > 0;
105-
boolean overrideButtonVisible = folder.type.equals(Constants.FOLDER_TYPE_SEND_ONLY) && outOfSync;
106-
binding.override.setVisibility(overrideButtonVisible ? VISIBLE : GONE);
107-
if (outOfSync) {
95+
if (folderStatus.isOutOfSync()) {
10896
binding.state.setText(mContext.getString(R.string.status_outofsync));
10997
binding.state.setTextColor(ContextCompat.getColor(mContext, R.color.text_red));
11098
} else {
@@ -185,5 +173,4 @@ private void setTextOrHide(TextView view, String text) {
185173
view.setVisibility(VISIBLE);
186174
}
187175
}
188-
189176
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<vector xmlns:android="http://schemas.android.com/apk/res/android"
2+
android:width="24dp"
3+
android:height="24dp"
4+
android:viewportWidth="24"
5+
android:viewportHeight="24"
6+
android:tint="?attr/colorControlNormal">
7+
<path
8+
android:fillColor="@android:color/white"
9+
android:pathData="M12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8s8,3.59 8,8S16.41,20 12,20M12,22c5.52,0 10,-4.48 10,-10c0,-5.52 -4.48,-10 -10,-10C6.48,2 2,6.48 2,12C2,17.52 6.48,22 12,22L12,22zM11,12l0,4h2l0,-4h3l-4,-4l-4,4H11z"/>
10+
</vector>

app/src/main/res/layout/fragment_folder.xml

+55
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,16 @@
217217
android:textAppearance="@style/TextAppearance.AppCompat.Caption"
218218
android:layout_marginBottom="10dp" />
219219

220+
</LinearLayout>
221+
222+
<LinearLayout
223+
android:id="@+id/ignoresContainer"
224+
android:layout_width="match_parent"
225+
android:layout_height="wrap_content"
226+
android:background="?selectableItemBackground"
227+
android:orientation="vertical"
228+
android:gravity="center_vertical">
229+
220230
<TextView
221231
android:id="@+id/edit_ignores"
222232
style="@style/Widget.Syncthing.TextView.Label.Details"
@@ -229,6 +239,51 @@
229239
android:text="@string/ignore_patterns"/>
230240

231241
</LinearLayout>
242+
243+
<LinearLayout
244+
android:id="@+id/actionsContainer"
245+
android:layout_width="match_parent"
246+
android:layout_height="wrap_content"
247+
android:background="?selectableItemBackground"
248+
android:orientation="vertical"
249+
android:gravity="center_vertical">
250+
251+
<LinearLayout
252+
android:id="@+id/overrideChangesContainer"
253+
android:layout_width="match_parent"
254+
android:layout_height="wrap_content"
255+
android:background="?selectableItemBackground"
256+
android:orientation="vertical"
257+
android:gravity="center_vertical"
258+
android:enabled="false">
259+
260+
<TextView
261+
android:id="@+id/overrideChanges"
262+
style="@style/Widget.Syncthing.TextView.Label.Details"
263+
android:layout_width="match_parent"
264+
android:layout_height="0dp"
265+
android:layout_weight="1"
266+
android:background="@null"
267+
android:checked="false"
268+
android:drawableLeft="@drawable/outline_arrow_circle_up_24"
269+
android:drawableStart="@drawable/outline_arrow_circle_up_24"
270+
android:text="@string/override_changes"
271+
android:enabled="false"
272+
/>
273+
274+
<TextView
275+
android:id="@+id/overrideChangesDescription"
276+
android:layout_width="match_parent"
277+
android:layout_height="wrap_content"
278+
android:layout_marginStart="72dp"
279+
android:layout_marginTop="-10dp"
280+
android:paddingBottom="10dp"
281+
android:textAppearance="@style/TextAppearance.AppCompat.Caption"
282+
android:text="@string/override_changes_description"
283+
android:enabled="false"/>
284+
285+
</LinearLayout>
286+
</LinearLayout>
232287
</LinearLayout>
233288
</ScrollView>
234289

app/src/main/res/layout/item_folder_list.xml

+1-16
Original file line numberDiff line numberDiff line change
@@ -44,26 +44,11 @@
4444
android:ellipsize="end"
4545
android:textAppearance="?textAppearanceListItemSecondary" />
4646

47-
<Button
48-
android:id="@+id/override"
49-
android:layout_width="wrap_content"
50-
android:layout_height="wrap_content"
51-
android:layout_below="@id/directory"
52-
android:contentDescription="@string/override_changes"
53-
android:paddingEnd="20dp"
54-
android:paddingLeft="20dp"
55-
android:paddingRight="20dp"
56-
android:paddingStart="20dp"
57-
android:text="@string/override_changes"
58-
android:drawableLeft="@android:drawable/ic_menu_upload"
59-
android:drawableStart="@android:drawable/ic_menu_upload"
60-
android:textSize="12sp" />
61-
6247
<TextView
6348
android:id="@+id/items"
6449
android:layout_width="wrap_content"
6550
android:layout_height="wrap_content"
66-
android:layout_below="@id/override"
51+
android:layout_below="@id/directory"
6752
android:textAppearance="?textAppearanceListItemSecondary" />
6853

6954
<TextView

app/src/main/res/values/strings.xml

+3-1
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,9 @@
116116
<item quantity="other">%1$d / %2$d Files</item>
117117
</plurals>
118118

119-
<string name="override_changes">Override changes</string>
119+
<string name="override_changes">Override Changes</string>
120+
<string name="override_changes_description">When configured as \"send only\" and changes have been made remotely, you may click here to overwrite the folder content on other devices.</string>
121+
<string name="override_changes_are_you_sure"><b>Warning!</b>\n\nThe folder content on other devices will be overwritten to become identical with this device. Files not present here will be deleted on other devices.\n\nAre you sure you want to continue?</string>
120122

121123
<string name="open_file_manager">Open file manager</string>
122124

0 commit comments

Comments
 (0)