diff options
Diffstat (limited to 'app/src')
21 files changed, 321 insertions, 0 deletions
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..9918188 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2026 Danilo M. <danix@danix.xyz> + Licensed under the GNU General Public License version 2 only. --> +<manifest xmlns:android="http://schemas.android.com/apk/res/android"> + + <uses-permission android:name="android.permission.INTERNET" /> + <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> + <uses-feature android:name="android.software.leanback" android:required="true" /> + <uses-feature android:name="android.hardware.touchscreen" android:required="false" /> + + <!-- Cleartext: Foldergram runs on the LAN over plain HTTP. + No backup: the viewer password lives in app preferences. --> + <application + android:name=".App" + android:allowBackup="false" + android:banner="@drawable/banner" + android:icon="@drawable/ic_folder" + android:label="mygram" + android:theme="@android:style/Theme.DeviceDefault.NoActionBar" + android:usesCleartextTraffic="true"> + <activity android:name=".MainActivity" android:exported="true"> + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="android.intent.category.LEANBACK_LAUNCHER" /> + <category android:name="android.intent.category.LAUNCHER" /> + </intent-filter> + </activity> + <activity android:name=".SetupActivity" /> + <activity android:name=".SettingsActivity" /> + <activity android:name=".FolderActivity" /> + <activity android:name=".ViewerActivity" /> + </application> +</manifest> diff --git a/app/src/main/java/mygram/droid/App.java b/app/src/main/java/mygram/droid/App.java new file mode 100644 index 0000000..ffbdd8d --- /dev/null +++ b/app/src/main/java/mygram/droid/App.java @@ -0,0 +1,32 @@ +/* + * 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.Application; + +import java.net.CookieHandler; +import java.net.CookieManager; +import java.net.CookiePolicy; + +public final class App extends Application { + @Override + public void onCreate() { + super.onCreate(); + Prefs.init(this); + // One cookie jar for the Foldergram session: Api, Glide and ExoPlayer + // all use HttpURLConnection, which consults the default handler. + CookieHandler.setDefault(new CookieManager(null, CookiePolicy.ACCEPT_ALL)); + } +} diff --git a/app/src/main/java/mygram/droid/FolderActivity.java b/app/src/main/java/mygram/droid/FolderActivity.java new file mode 100644 index 0000000..d53588a --- /dev/null +++ b/app/src/main/java/mygram/droid/FolderActivity.java @@ -0,0 +1,20 @@ +/* + * 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; + +public final class FolderActivity extends Activity { +} diff --git a/app/src/main/java/mygram/droid/MainActivity.java b/app/src/main/java/mygram/droid/MainActivity.java new file mode 100644 index 0000000..767dbb1 --- /dev/null +++ b/app/src/main/java/mygram/droid/MainActivity.java @@ -0,0 +1,20 @@ +/* + * 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; + +public final class MainActivity extends Activity { +} diff --git a/app/src/main/java/mygram/droid/Prefs.java b/app/src/main/java/mygram/droid/Prefs.java new file mode 100644 index 0000000..33ce878 --- /dev/null +++ b/app/src/main/java/mygram/droid/Prefs.java @@ -0,0 +1,60 @@ +/* + * 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.content.Context; +import android.content.SharedPreferences; + +/** Settings stored on the device. */ +final class Prefs { + private static SharedPreferences prefs; + + private Prefs() { + } + + static void init(Context c) { + prefs = c.getSharedPreferences("mygram", Context.MODE_PRIVATE); + } + + /** Base URL like "http://192.0.2.10:4141", or null before setup. */ + static String server() { + return prefs.getString("server", null); + } + + /** Viewer password; empty for a public instance. */ + static String password() { + return prefs.getString("password", ""); + } + + static int photoSeconds() { + return prefs.getInt("photo", 8); + } + + static int backgroundSeconds() { + return prefs.getInt("background", 15); + } + + static void setServer(String base, String password) { + prefs.edit().putString("server", base).putString("password", password).apply(); + } + + static void setPassword(String password) { + prefs.edit().putString("password", password).apply(); + } + + static void setTimes(int photo, int background) { + prefs.edit().putInt("photo", photo).putInt("background", background).apply(); + } +} diff --git a/app/src/main/java/mygram/droid/SettingsActivity.java b/app/src/main/java/mygram/droid/SettingsActivity.java new file mode 100644 index 0000000..776e48b --- /dev/null +++ b/app/src/main/java/mygram/droid/SettingsActivity.java @@ -0,0 +1,20 @@ +/* + * 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; + +public final class SettingsActivity extends Activity { +} diff --git a/app/src/main/java/mygram/droid/SetupActivity.java b/app/src/main/java/mygram/droid/SetupActivity.java new file mode 100644 index 0000000..ef1f68c --- /dev/null +++ b/app/src/main/java/mygram/droid/SetupActivity.java @@ -0,0 +1,20 @@ +/* + * 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; + +public final class SetupActivity extends Activity { +} diff --git a/app/src/main/java/mygram/droid/ViewerActivity.java b/app/src/main/java/mygram/droid/ViewerActivity.java new file mode 100644 index 0000000..9a3be55 --- /dev/null +++ b/app/src/main/java/mygram/droid/ViewerActivity.java @@ -0,0 +1,20 @@ +/* + * 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; + +public final class ViewerActivity extends Activity { +} diff --git a/app/src/main/res/drawable/banner.xml b/app/src/main/res/drawable/banner.xml new file mode 100644 index 0000000..e1a075a --- /dev/null +++ b/app/src/main/res/drawable/banner.xml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2026 Danilo M. <danix@danix.xyz> + Licensed under the GNU General Public License version 2 only. --> +<layer-list xmlns:android="http://schemas.android.com/apk/res/android"> + <item> + <shape> + <solid android:color="#FF4F46E5" /> + <size android:width="320dp" android:height="180dp" /> + </shape> + </item> + <item android:drawable="@drawable/ic_folder" android:gravity="center" + android:width="96dp" android:height="96dp" /> +</layer-list> diff --git a/app/src/main/res/drawable/focus_ring.xml b/app/src/main/res/drawable/focus_ring.xml new file mode 100644 index 0000000..1cab3f8 --- /dev/null +++ b/app/src/main/res/drawable/focus_ring.xml @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2026 Danilo M. <danix@danix.xyz> + Licensed under the GNU General Public License version 2 only. --> +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:state_focused="true"> + <shape> + <corners android:radius="8dp" /> + <stroke android:width="3dp" android:color="#FFFFFFFF" /> + </shape> + </item> + <item> + <shape> + <corners android:radius="8dp" /> + <solid android:color="#00000000" /> + </shape> + </item> +</selector> diff --git a/app/src/main/res/drawable/ic_arrow_forward.xml b/app/src/main/res/drawable/ic_arrow_forward.xml new file mode 100644 index 0000000..4b3cf6d --- /dev/null +++ b/app/src/main/res/drawable/ic_arrow_forward.xml @@ -0,0 +1,6 @@ +<!-- Material Icons "arrow_forward", Apache License 2.0 --> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" android:height="24dp" + android:viewportWidth="24" android:viewportHeight="24"> + <path android:fillColor="#FFFFFFFF" android:pathData="M12,4l-1.41,1.41L16.17,11H4v2h12.17l-5.58,5.59L12,20l8,-8z" /> +</vector> diff --git a/app/src/main/res/drawable/ic_check.xml b/app/src/main/res/drawable/ic_check.xml new file mode 100644 index 0000000..ef81024 --- /dev/null +++ b/app/src/main/res/drawable/ic_check.xml @@ -0,0 +1,6 @@ +<!-- Material Icons "check", Apache License 2.0 --> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" android:height="24dp" + android:viewportWidth="24" android:viewportHeight="24"> + <path android:fillColor="#FFFFFFFF" android:pathData="M9,16.17L4.83,12l-1.42,1.41L9,19 21,7l-1.41,-1.41z" /> +</vector> diff --git a/app/src/main/res/drawable/ic_edit.xml b/app/src/main/res/drawable/ic_edit.xml new file mode 100644 index 0000000..35b45bb --- /dev/null +++ b/app/src/main/res/drawable/ic_edit.xml @@ -0,0 +1,6 @@ +<!-- Material Icons "edit", Apache License 2.0 --> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" android:height="24dp" + android:viewportWidth="24" android:viewportHeight="24"> + <path android:fillColor="#FFFFFFFF" android:pathData="M3,17.25V21h3.75L17.81,9.94l-3.75,-3.75L3,17.25zM20.71,7.04c0.39,-0.39 0.39,-1.02 0,-1.41l-2.34,-2.34c-0.39,-0.39 -1.02,-0.39 -1.41,0l-1.83,1.83 3.75,3.75 1.83,-1.83z" /> +</vector> diff --git a/app/src/main/res/drawable/ic_favorite.xml b/app/src/main/res/drawable/ic_favorite.xml new file mode 100644 index 0000000..ccd588f --- /dev/null +++ b/app/src/main/res/drawable/ic_favorite.xml @@ -0,0 +1,6 @@ +<!-- Material Icons "favorite", Apache License 2.0 --> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" android:height="24dp" + android:viewportWidth="24" android:viewportHeight="24"> + <path android:fillColor="#FFFFFFFF" android:pathData="M12,21.35l-1.45,-1.32C5.4,15.36 2,12.28 2,8.5 2,5.42 4.42,3 7.5,3c1.74,0 3.41,0.81 4.5,2.09C13.09,3.81 14.76,3 16.5,3 19.58,3 22,5.42 22,8.5c0,3.78 -3.4,6.86 -8.55,11.54L12,21.35z" /> +</vector> diff --git a/app/src/main/res/drawable/ic_folder.xml b/app/src/main/res/drawable/ic_folder.xml new file mode 100644 index 0000000..16c7032 --- /dev/null +++ b/app/src/main/res/drawable/ic_folder.xml @@ -0,0 +1,6 @@ +<!-- Material Icons "folder", Apache License 2.0 --> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" android:height="24dp" + android:viewportWidth="24" android:viewportHeight="24"> + <path android:fillColor="#FFFFFFFF" android:pathData="M10,4H4c-1.1,0 -1.99,0.9 -1.99,2L2,18c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2V8c0,-1.1 -0.9,-2 -2,-2h-8l-2,-2z" /> +</vector> diff --git a/app/src/main/res/drawable/ic_home.xml b/app/src/main/res/drawable/ic_home.xml new file mode 100644 index 0000000..5503d0c --- /dev/null +++ b/app/src/main/res/drawable/ic_home.xml @@ -0,0 +1,6 @@ +<!-- Material Icons "home", Apache License 2.0 --> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" android:height="24dp" + android:viewportWidth="24" android:viewportHeight="24"> + <path android:fillColor="#FFFFFFFF" android:pathData="M10,20v-6h4v6h5v-8h3L12,3 2,12h3v8z" /> +</vector> diff --git a/app/src/main/res/drawable/ic_pause.xml b/app/src/main/res/drawable/ic_pause.xml new file mode 100644 index 0000000..1a87d2a --- /dev/null +++ b/app/src/main/res/drawable/ic_pause.xml @@ -0,0 +1,6 @@ +<!-- Material Icons "pause", Apache License 2.0 --> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" android:height="24dp" + android:viewportWidth="24" android:viewportHeight="24"> + <path android:fillColor="#FFFFFFFF" android:pathData="M6,19h4V5H6v14zM14,5v14h4V5h-4z" /> +</vector> diff --git a/app/src/main/res/drawable/ic_reels.xml b/app/src/main/res/drawable/ic_reels.xml new file mode 100644 index 0000000..f4dda6d --- /dev/null +++ b/app/src/main/res/drawable/ic_reels.xml @@ -0,0 +1,6 @@ +<!-- Material Icons "reels", Apache License 2.0 --> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" android:height="24dp" + android:viewportWidth="24" android:viewportHeight="24"> + <path android:fillColor="#FFFFFFFF" android:pathData="M4,6H2v14c0,1.1 0.9,2 2,2h14v-2H4V6zM20,2H8c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2V4c0,-1.1 -0.9,-2 -2,-2zM12,14.5v-9l6,4.5 -6,4.5z" /> +</vector> diff --git a/app/src/main/res/drawable/ic_refresh.xml b/app/src/main/res/drawable/ic_refresh.xml new file mode 100644 index 0000000..41fa710 --- /dev/null +++ b/app/src/main/res/drawable/ic_refresh.xml @@ -0,0 +1,6 @@ +<!-- Material Icons "refresh", Apache License 2.0 --> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" android:height="24dp" + android:viewportWidth="24" android:viewportHeight="24"> + <path android:fillColor="#FFFFFFFF" android:pathData="M17.65,6.35C16.2,4.9 14.21,4 12,4c-4.42,0 -7.99,3.58 -7.99,8s3.57,8 7.99,8c3.73,0 6.84,-2.55 7.73,-6h-2.08c-0.82,2.33 -3.04,4 -5.65,4 -3.31,0 -6,-2.69 -6,-6s2.69,-6 6,-6c1.66,0 3.14,0.69 4.22,1.78L13,11h7V4l-2.35,2.35z" /> +</vector> diff --git a/app/src/main/res/drawable/ic_settings.xml b/app/src/main/res/drawable/ic_settings.xml new file mode 100644 index 0000000..2afd04d --- /dev/null +++ b/app/src/main/res/drawable/ic_settings.xml @@ -0,0 +1,6 @@ +<!-- Material Icons "settings", Apache License 2.0 --> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" android:height="24dp" + android:viewportWidth="24" android:viewportHeight="24"> + <path android:fillColor="#FFFFFFFF" android:pathData="M19.14,12.94c0.04,-0.3 0.06,-0.61 0.06,-0.94c0,-0.32 -0.02,-0.64 -0.07,-0.94l2.03,-1.58c0.18,-0.14 0.23,-0.41 0.12,-0.61l-1.92,-3.32c-0.12,-0.22 -0.37,-0.29 -0.59,-0.22l-2.39,0.96c-0.5,-0.38 -1.03,-0.7 -1.62,-0.94L14.4,2.81c-0.04,-0.24 -0.24,-0.41 -0.48,-0.41h-3.84c-0.24,0 -0.43,0.17 -0.47,0.41L9.25,5.35C8.66,5.59 8.12,5.92 7.63,6.29L5.24,5.33c-0.22,-0.08 -0.47,0 -0.59,0.22L2.74,8.87C2.62,9.08 2.66,9.34 2.86,9.48l2.03,1.58C4.84,11.36 4.8,11.69 4.8,12s0.02,0.64 0.07,0.94l-2.03,1.58c-0.18,0.14 -0.23,0.41 -0.12,0.61l1.92,3.32c0.12,0.22 0.37,0.29 0.59,0.22l2.39,-0.96c0.5,0.38 1.03,0.7 1.62,0.94l0.36,2.54c0.05,0.24 0.24,0.41 0.48,0.41h3.84c0.24,0 0.44,-0.17 0.47,-0.41l0.36,-2.54c0.59,-0.24 1.13,-0.56 1.62,-0.94l2.39,0.96c0.22,0.08 0.47,0 0.59,-0.22l1.92,-3.32c0.12,-0.22 0.07,-0.47 -0.12,-0.61L19.14,12.94zM12,15.6c-1.98,0 -3.6,-1.62 -3.6,-3.6s1.62,-3.6 3.6,-3.6s3.6,1.62 3.6,3.6S13.98,15.6 12,15.6z" /> +</vector> diff --git a/app/src/main/res/drawable/ic_swap.xml b/app/src/main/res/drawable/ic_swap.xml new file mode 100644 index 0000000..ba3591d --- /dev/null +++ b/app/src/main/res/drawable/ic_swap.xml @@ -0,0 +1,6 @@ +<!-- Material Icons "swap", Apache License 2.0 --> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" android:height="24dp" + android:viewportWidth="24" android:viewportHeight="24"> + <path android:fillColor="#FFFFFFFF" android:pathData="M6.99,11L3,15l3.99,4v-3H14v-2H6.99v-3zM21,9l-3.99,-4v3H10v2h7.01v3L21,9z" /> +</vector> |
