aboutsummaryrefslogtreecommitdiffstats
path: root/app/src/main/java/mygram/droid/SetupActivity.java
blob: 106ec9cc6f39deb34d8bb3aa283c693c7eca9228 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
/*
 * mygram-droid: Android TV client for Foldergram.
 * Copyright (C) 2026 Danilo M. <danix@danix.xyz>
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 as published
 * by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
 * for more details.
 */

package mygram.droid;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.text.InputType;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;

import java.util.LinkedHashMap;
import java.util.Map;

/** Instance picker: LAN scan, manual URL, then the password when the instance asks for one. */
public final class SetupActivity extends Activity {
	private LinearLayout box;

	@Override
	protected void onCreate(Bundle state) {
		super.onCreate(state);
		box = Ui.column(this);
		setContentView(box);
		scan();
	}

	private void scan() {
		reset("Searching the network for Foldergram…");
		Api.async(() -> {
			Map<String, String> found = new LinkedHashMap<>();
			String self = Discovery.localIpv4(this);
			if (self != null)
				for (String base : Discovery.scan(self))
					found.put(base, Discovery.label(base));
			return found;
		}, this::found, e -> {
			reset("Scan failed: " + e.getMessage());
			actions();
		});
	}

	private void found(Map<String, String> instances) {
		reset(instances.isEmpty() ? "No Foldergram found on port " + Discovery.PORT : "Choose an instance");
		for (Map.Entry<String, String> e : instances.entrySet()) {
			TextView t = Ui.text(this, e.getValue(), 20);
			int p = Ui.dp(this, 12);
			t.setPadding(p * 2, p, p * 2, p);
			Ui.focusable(t);
			t.setOnClickListener(v -> choose(e.getKey()));
			box.addView(t);
		}
		actions();
		box.getChildAt(1).requestFocus();
	}

	private void actions() {
		LinearLayout row = Ui.row(this);
		row.addView(Ui.iconButton(this, R.drawable.ic_refresh, "Rescan", v -> scan()));
		row.addView(Ui.iconButton(this, R.drawable.ic_edit, "Enter URL", v -> manual()));
		box.addView(row);
	}

	private void manual() {
		reset("Instance URL");
		EditText url = Ui.field(this, "http://host:" + Discovery.PORT,
				InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_URI);
		box.addView(url);
		box.addView(Ui.iconButton(this, R.drawable.ic_check, "Connect",
				v -> choose(Api.normalize(url.getText().toString()))));
		url.requestFocus();
	}

	private void choose(String base) {
		reset("Connecting to " + base + "…");
		Api.async(() -> Api.authStatus(base), status -> {
			if ("public".equals(status.optString("accessMode")))
				save(base, "");
			else
				password(base);
		}, e -> {
			reset("Cannot reach " + base + ": " + e.getMessage());
			actions();
		});
	}

	private void password(String base) {
		reset("Viewer password for " + base);
		EditText pw = Ui.field(this, "Password", Ui.password());
		box.addView(pw);
		box.addView(Ui.iconButton(this, R.drawable.ic_check, "Log in", v -> {
			String s = pw.getText().toString();
			Api.async(() -> {
				Api.login(base, s);
				return true;
			}, ok -> save(base, s), e -> Toast.makeText(this,
					e instanceof Api.HttpError && ((Api.HttpError) e).code == 401 ? "Wrong password" : e.getMessage(),
					Toast.LENGTH_LONG).show());
		}));
		pw.requestFocus();
	}

	private void save(String base, String password) {
		Prefs.setServer(base, password);
		startActivity(new Intent(this, MainActivity.class)
				.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK));
	}

	private void reset(String title) {
		box.removeAllViews();
		box.addView(Ui.text(this, title, 24));
	}
}