├── .gitignore
├── .vscode
└── extensions.json
├── README.md
├── bun.lockb
├── index.html
├── package.json
├── public
├── tauri.svg
└── vite.svg
├── src-tauri
├── .gitignore
├── Cargo.lock
├── Cargo.toml
├── build.rs
├── capabilities
│ └── default.json
├── gen
│ └── android
│ │ ├── .editorconfig
│ │ ├── .gitignore
│ │ ├── app
│ │ ├── .gitignore
│ │ ├── build.gradle.kts
│ │ ├── debug.keystore
│ │ ├── proguard-rules.pro
│ │ └── src
│ │ │ └── main
│ │ │ ├── AndroidManifest.xml
│ │ │ ├── java
│ │ │ └── com
│ │ │ │ └── follow
│ │ │ │ └── app
│ │ │ │ └── MainActivity.kt
│ │ │ └── res
│ │ │ ├── drawable-v24
│ │ │ └── ic_launcher_foreground.xml
│ │ │ ├── drawable
│ │ │ └── ic_launcher_background.xml
│ │ │ ├── layout
│ │ │ └── activity_main.xml
│ │ │ ├── mipmap-hdpi
│ │ │ ├── ic_launcher.png
│ │ │ ├── ic_launcher_foreground.png
│ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-mdpi
│ │ │ ├── ic_launcher.png
│ │ │ ├── ic_launcher_foreground.png
│ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-xhdpi
│ │ │ ├── ic_launcher.png
│ │ │ ├── ic_launcher_foreground.png
│ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-xxhdpi
│ │ │ ├── ic_launcher.png
│ │ │ ├── ic_launcher_foreground.png
│ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-xxxhdpi
│ │ │ ├── ic_launcher.png
│ │ │ ├── ic_launcher_foreground.png
│ │ │ └── ic_launcher_round.png
│ │ │ ├── values-night
│ │ │ └── themes.xml
│ │ │ ├── values
│ │ │ ├── colors.xml
│ │ │ ├── strings.xml
│ │ │ └── themes.xml
│ │ │ └── xml
│ │ │ └── file_paths.xml
│ │ ├── build.gradle.kts
│ │ ├── buildSrc
│ │ ├── build.gradle.kts
│ │ └── src
│ │ │ └── main
│ │ │ └── java
│ │ │ └── com
│ │ │ └── follow
│ │ │ └── app
│ │ │ └── kotlin
│ │ │ ├── BuildTask.kt
│ │ │ └── RustPlugin.kt
│ │ ├── gradle.properties
│ │ ├── gradle
│ │ └── wrapper
│ │ │ ├── gradle-wrapper.jar
│ │ │ └── gradle-wrapper.properties
│ │ ├── gradlew
│ │ ├── gradlew.bat
│ │ └── settings.gradle
├── icons
│ ├── 128x128.png
│ ├── 128x128@2x.png
│ ├── 32x32.png
│ ├── Square107x107Logo.png
│ ├── Square142x142Logo.png
│ ├── Square150x150Logo.png
│ ├── Square284x284Logo.png
│ ├── Square30x30Logo.png
│ ├── Square310x310Logo.png
│ ├── Square44x44Logo.png
│ ├── Square71x71Logo.png
│ ├── Square89x89Logo.png
│ ├── StoreLogo.png
│ ├── icon.icns
│ ├── icon.ico
│ ├── icon.png
│ └── ios
│ │ ├── AppIcon-20x20@1x.png
│ │ ├── AppIcon-20x20@2x-1.png
│ │ ├── AppIcon-20x20@2x.png
│ │ ├── AppIcon-20x20@3x.png
│ │ ├── AppIcon-29x29@1x.png
│ │ ├── AppIcon-29x29@2x-1.png
│ │ ├── AppIcon-29x29@2x.png
│ │ ├── AppIcon-29x29@3x.png
│ │ ├── AppIcon-40x40@1x.png
│ │ ├── AppIcon-40x40@2x-1.png
│ │ ├── AppIcon-40x40@2x.png
│ │ ├── AppIcon-40x40@3x.png
│ │ ├── AppIcon-512@2x.png
│ │ ├── AppIcon-60x60@2x.png
│ │ ├── AppIcon-60x60@3x.png
│ │ ├── AppIcon-76x76@1x.png
│ │ ├── AppIcon-76x76@2x.png
│ │ └── AppIcon-83.5x83.5@2x.png
├── src
│ ├── lib.rs
│ └── main.rs
└── tauri.conf.json
├── src
├── App.css
├── App.tsx
├── assets
│ └── react.svg
├── main.tsx
├── sw.js
└── vite-env.d.ts
├── tsconfig.json
├── tsconfig.node.json
└── vite.config.ts
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | pnpm-debug.log*
8 | lerna-debug.log*
9 |
10 | node_modules
11 | dist
12 | dist-ssr
13 | *.local
14 |
15 | keystore.properties
16 |
17 | # Editor directories and files
18 | .vscode/*
19 | !.vscode/extensions.json
20 | .idea
21 | .DS_Store
22 | *.suo
23 | *.ntvs*
24 | *.njsproj
25 | *.sln
26 | *.sw?
27 |
--------------------------------------------------------------------------------
/.vscode/extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | "recommendations": ["tauri-apps.tauri-vscode", "rust-lang.rust-analyzer"]
3 | }
4 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 📝 项目介绍
2 |
3 | 整体项目很简单,就是通过Webview打开Follow.is的网站,然后用Tauri生成Android编译APK所需要的文件,最后进行打包。整体APP大小在28M左右,暂时还没有做任何优化,先占个坑,在后续自己使用过程中如果发现问题会进行更新。
4 |
5 | ## 支持功能
6 |
7 | - Google和Github的登录可用
8 | - RSS正常可以阅读(Youtube订阅源暂时无法直接播放视频)
9 | - 添加订阅源正常
10 | - 大部分页面显示正常(目前还没有找到不正常的)
11 | - 使用SW进行缓存
12 |
--------------------------------------------------------------------------------
/bun.lockb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/moreoronce/followforandroid/2be607b61ae24aa5d475a01463fd7a546c57f9c5/bun.lockb
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Tauri + React + Typescript
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "follow",
3 | "private": true,
4 | "version": "0.1.1",
5 | "type": "module",
6 | "scripts": {
7 | "dev": "vite",
8 | "build": "tsc && vite build",
9 | "preview": "vite preview",
10 | "tauri": "tauri"
11 | },
12 | "dependencies": {
13 | "@tauri-apps/api": "^2",
14 | "@tauri-apps/plugin-opener": "^2",
15 | "react": "^18.3.1",
16 | "react-dom": "^18.3.1",
17 | "vite-plugin-pwa": "^0.21.1"
18 | },
19 | "devDependencies": {
20 | "@types/react": "^18.3.1",
21 | "@types/react-dom": "^18.3.1",
22 | "@vitejs/plugin-react": "^4.3.4",
23 | "typescript": "~5.6.2",
24 | "vite": "^6.0.3",
25 | "@tauri-apps/cli": "^2"
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/public/tauri.svg:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/public/vite.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src-tauri/.gitignore:
--------------------------------------------------------------------------------
1 | # Generated by Cargo
2 | # will have compiled files and executables
3 | /target/
4 |
5 | # Generated by Tauri
6 | # will have schema files for capabilities auto-completion
7 | /gen/schemas
8 |
--------------------------------------------------------------------------------
/src-tauri/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "follow"
3 | version = "0.1.1"
4 | description = "A Tauri App"
5 | authors = ["you"]
6 | edition = "2021"
7 |
8 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
9 |
10 | [lib]
11 | # The `_lib` suffix may seem redundant but it is necessary
12 | # to make the lib name unique and wouldn't conflict with the bin name.
13 | # This seems to be only an issue on Windows, see https://github.com/rust-lang/cargo/issues/8519
14 | name = "follow_lib"
15 | crate-type = ["staticlib", "cdylib", "rlib"]
16 |
17 | [build-dependencies]
18 | tauri-build = { version = "2", features = [] }
19 |
20 | [dependencies]
21 | tauri = { version = "2", features = [] }
22 | tauri-plugin-opener = "2"
23 | serde = { version = "1", features = ["derive"] }
24 | serde_json = "1"
25 |
26 |
--------------------------------------------------------------------------------
/src-tauri/build.rs:
--------------------------------------------------------------------------------
1 | fn main() {
2 | tauri_build::build()
3 | }
4 |
--------------------------------------------------------------------------------
/src-tauri/capabilities/default.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "../gen/schemas/desktop-schema.json",
3 | "identifier": "default",
4 | "description": "Capability for the main window",
5 | "windows": ["main"],
6 | "permissions": [
7 | "core:default",
8 | "opener:default"
9 | ]
10 | }
11 |
--------------------------------------------------------------------------------
/src-tauri/gen/android/.editorconfig:
--------------------------------------------------------------------------------
1 | # EditorConfig is awesome: https://EditorConfig.org
2 |
3 | # top-most EditorConfig file
4 | root = true
5 |
6 | [*]
7 | indent_style = space
8 | indent_size = 2
9 | end_of_line = lf
10 | charset = utf-8
11 | trim_trailing_whitespace = false
12 | insert_final_newline = false
--------------------------------------------------------------------------------
/src-tauri/gen/android/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/caches
5 | /.idea/libraries
6 | /.idea/modules.xml
7 | /.idea/workspace.xml
8 | /.idea/navEditor.xml
9 | /.idea/assetWizardSettings.xml
10 | .DS_Store
11 | build
12 | /captures
13 | .externalNativeBuild
14 | .cxx
15 | local.properties
16 | key.properties
17 |
18 | /.tauri
19 | /tauri.settings.gradle
--------------------------------------------------------------------------------
/src-tauri/gen/android/app/.gitignore:
--------------------------------------------------------------------------------
1 | /src/main/java/com/follow/app/generated
2 | /src/main/jniLibs/**/*.so
3 | /src/main/assets/tauri.conf.json
4 | /tauri.build.gradle.kts
5 | /proguard-tauri.pro
6 | /tauri.properties
--------------------------------------------------------------------------------
/src-tauri/gen/android/app/build.gradle.kts:
--------------------------------------------------------------------------------
1 | import java.util.Properties
2 | import java.io.FileInputStream
3 |
4 | plugins {
5 | id("com.android.application")
6 | id("org.jetbrains.kotlin.android")
7 | id("rust")
8 | }
9 |
10 | val tauriProperties = Properties().apply {
11 | val propFile = file("tauri.properties")
12 | if (propFile.exists()) {
13 | propFile.inputStream().use { load(it) }
14 | }
15 | }
16 |
17 | android {
18 | compileSdk = 33
19 | namespace = "com.follow.app"
20 | defaultConfig {
21 | manifestPlaceholders["usesCleartextTraffic"] = "false"
22 | applicationId = "com.follow.app"
23 | minSdk = 24
24 | targetSdk = 33
25 | versionCode = tauriProperties.getProperty("tauri.android.versionCode", "1").toInt()
26 | versionName = tauriProperties.getProperty("tauri.android.versionName", "1.0")
27 | }
28 | signingConfigs {
29 | create("release") {
30 | val keystorePropertiesFile = rootProject.file("keystore.properties")
31 | val keystoreProperties = Properties()
32 | if (keystorePropertiesFile.exists()) {
33 | keystoreProperties.load(FileInputStream(keystorePropertiesFile))
34 | }
35 |
36 | keyAlias = keystoreProperties["keyAlias"] as String
37 | keyPassword = keystoreProperties["keyPassword"] as String
38 | storeFile = file(keystoreProperties["storeFile"] as String)
39 | storePassword = keystoreProperties["storePassword"] as String
40 | }
41 | }
42 |
43 | buildTypes {
44 | getByName("debug") {
45 | manifestPlaceholders["usesCleartextTraffic"] = "true"
46 | isDebuggable = true
47 | isJniDebuggable = true
48 | isMinifyEnabled = false
49 | packaging { jniLibs.keepDebugSymbols.add("*/arm64-v8a/*.so")
50 | jniLibs.keepDebugSymbols.add("*/armeabi-v7a/*.so")
51 | jniLibs.keepDebugSymbols.add("*/x86/*.so")
52 | jniLibs.keepDebugSymbols.add("*/x86_64/*.so")
53 | }
54 | }
55 | getByName("release") {
56 | signingConfig = signingConfigs.getByName("release")
57 | isMinifyEnabled = true
58 | proguardFiles(
59 | *fileTree(".") { include("**/*.pro") }
60 | .plus(getDefaultProguardFile("proguard-android-optimize.txt"))
61 | .toList().toTypedArray()
62 | )
63 | }
64 | }
65 | kotlinOptions {
66 | jvmTarget = "1.8"
67 | }
68 | buildFeatures {
69 | buildConfig = true
70 | }
71 | }
72 |
73 | rust {
74 | rootDirRel = "../../../"
75 | }
76 |
77 | dependencies {
78 | implementation("androidx.webkit:webkit:1.6.1")
79 | implementation("androidx.appcompat:appcompat:1.6.1")
80 | implementation("com.google.android.material:material:1.8.0")
81 | testImplementation("junit:junit:4.13.2")
82 | androidTestImplementation("androidx.test.ext:junit:1.1.4")
83 | androidTestImplementation("androidx.test.espresso:espresso-core:3.5.0")
84 | }
85 |
86 | apply(from = "tauri.build.gradle.kts")
--------------------------------------------------------------------------------
/src-tauri/gen/android/app/debug.keystore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/moreoronce/followforandroid/2be607b61ae24aa5d475a01463fd7a546c57f9c5/src-tauri/gen/android/app/debug.keystore
--------------------------------------------------------------------------------
/src-tauri/gen/android/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
--------------------------------------------------------------------------------
/src-tauri/gen/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
13 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
32 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/src-tauri/gen/android/app/src/main/java/com/follow/app/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package com.follow.app
2 |
3 | class MainActivity : TauriActivity()
--------------------------------------------------------------------------------
/src-tauri/gen/android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
15 |
18 |
21 |
22 |
23 |
24 |
30 |
--------------------------------------------------------------------------------
/src-tauri/gen/android/app/src/main/res/drawable/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
10 |
15 |
20 |
25 |
30 |
35 |
40 |
45 |
50 |
55 |
60 |
65 |
70 |
75 |
80 |
85 |
90 |
95 |
100 |
105 |
110 |
115 |
120 |
125 |
130 |
135 |
140 |
145 |
150 |
155 |
160 |
165 |
170 |
171 |
--------------------------------------------------------------------------------
/src-tauri/gen/android/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
17 |
18 |
--------------------------------------------------------------------------------
/src-tauri/gen/android/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/moreoronce/followforandroid/2be607b61ae24aa5d475a01463fd7a546c57f9c5/src-tauri/gen/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/src-tauri/gen/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/moreoronce/followforandroid/2be607b61ae24aa5d475a01463fd7a546c57f9c5/src-tauri/gen/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/src-tauri/gen/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/moreoronce/followforandroid/2be607b61ae24aa5d475a01463fd7a546c57f9c5/src-tauri/gen/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/src-tauri/gen/android/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/moreoronce/followforandroid/2be607b61ae24aa5d475a01463fd7a546c57f9c5/src-tauri/gen/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/src-tauri/gen/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/moreoronce/followforandroid/2be607b61ae24aa5d475a01463fd7a546c57f9c5/src-tauri/gen/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/src-tauri/gen/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/moreoronce/followforandroid/2be607b61ae24aa5d475a01463fd7a546c57f9c5/src-tauri/gen/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/src-tauri/gen/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/moreoronce/followforandroid/2be607b61ae24aa5d475a01463fd7a546c57f9c5/src-tauri/gen/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/src-tauri/gen/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/moreoronce/followforandroid/2be607b61ae24aa5d475a01463fd7a546c57f9c5/src-tauri/gen/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/src-tauri/gen/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/moreoronce/followforandroid/2be607b61ae24aa5d475a01463fd7a546c57f9c5/src-tauri/gen/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/src-tauri/gen/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/moreoronce/followforandroid/2be607b61ae24aa5d475a01463fd7a546c57f9c5/src-tauri/gen/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/src-tauri/gen/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/moreoronce/followforandroid/2be607b61ae24aa5d475a01463fd7a546c57f9c5/src-tauri/gen/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/src-tauri/gen/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/moreoronce/followforandroid/2be607b61ae24aa5d475a01463fd7a546c57f9c5/src-tauri/gen/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/src-tauri/gen/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/moreoronce/followforandroid/2be607b61ae24aa5d475a01463fd7a546c57f9c5/src-tauri/gen/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/src-tauri/gen/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/moreoronce/followforandroid/2be607b61ae24aa5d475a01463fd7a546c57f9c5/src-tauri/gen/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/src-tauri/gen/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/moreoronce/followforandroid/2be607b61ae24aa5d475a01463fd7a546c57f9c5/src-tauri/gen/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/src-tauri/gen/android/app/src/main/res/values-night/themes.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
--------------------------------------------------------------------------------
/src-tauri/gen/android/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #FFBB86FC
4 | #FF6200EE
5 | #FF3700B3
6 | #FF03DAC5
7 | #FF018786
8 | #FF000000
9 | #FFFFFFFF
10 |
--------------------------------------------------------------------------------
/src-tauri/gen/android/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | follow
3 | follow
4 |
--------------------------------------------------------------------------------
/src-tauri/gen/android/app/src/main/res/values/themes.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
8 |
--------------------------------------------------------------------------------
/src-tauri/gen/android/app/src/main/res/xml/file_paths.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/src-tauri/gen/android/build.gradle.kts:
--------------------------------------------------------------------------------
1 | buildscript {
2 | repositories {
3 | google()
4 | mavenCentral()
5 | }
6 | dependencies {
7 | classpath("com.android.tools.build:gradle:8.5.1")
8 | classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.25")
9 | }
10 | }
11 |
12 | allprojects {
13 | repositories {
14 | google()
15 | mavenCentral()
16 | }
17 | }
18 |
19 | tasks.register("clean").configure {
20 | delete("build")
21 | }
22 |
23 |
--------------------------------------------------------------------------------
/src-tauri/gen/android/buildSrc/build.gradle.kts:
--------------------------------------------------------------------------------
1 | plugins {
2 | `kotlin-dsl`
3 | }
4 |
5 | gradlePlugin {
6 | plugins {
7 | create("pluginsForCoolKids") {
8 | id = "rust"
9 | implementationClass = "RustPlugin"
10 | }
11 | }
12 | }
13 |
14 | repositories {
15 | google()
16 | mavenCentral()
17 | }
18 |
19 | dependencies {
20 | compileOnly(gradleApi())
21 | implementation("com.android.tools.build:gradle:8.5.1")
22 | }
23 |
24 |
--------------------------------------------------------------------------------
/src-tauri/gen/android/buildSrc/src/main/java/com/follow/app/kotlin/BuildTask.kt:
--------------------------------------------------------------------------------
1 | import java.io.File
2 | import org.apache.tools.ant.taskdefs.condition.Os
3 | import org.gradle.api.DefaultTask
4 | import org.gradle.api.GradleException
5 | import org.gradle.api.logging.LogLevel
6 | import org.gradle.api.tasks.Input
7 | import org.gradle.api.tasks.TaskAction
8 |
9 | open class BuildTask : DefaultTask() {
10 | @Input
11 | var rootDirRel: String? = null
12 | @Input
13 | var target: String? = null
14 | @Input
15 | var release: Boolean? = null
16 |
17 | @TaskAction
18 | fun assemble() {
19 | val executable = """bun""";
20 | try {
21 | runTauriCli(executable)
22 | } catch (e: Exception) {
23 | if (Os.isFamily(Os.FAMILY_WINDOWS)) {
24 | runTauriCli("$executable.cmd")
25 | } else {
26 | throw e;
27 | }
28 | }
29 | }
30 |
31 | fun runTauriCli(executable: String) {
32 | val rootDirRel = rootDirRel ?: throw GradleException("rootDirRel cannot be null")
33 | val target = target ?: throw GradleException("target cannot be null")
34 | val release = release ?: throw GradleException("release cannot be null")
35 | val args = listOf("tauri", "android", "android-studio-script");
36 |
37 | project.exec {
38 | workingDir(File(project.projectDir, rootDirRel))
39 | executable(executable)
40 | args(args)
41 | if (project.logger.isEnabled(LogLevel.DEBUG)) {
42 | args("-vv")
43 | } else if (project.logger.isEnabled(LogLevel.INFO)) {
44 | args("-v")
45 | }
46 | if (release) {
47 | args("--release")
48 | }
49 | args(listOf("--target", target))
50 | }.assertNormalExitValue()
51 | }
52 | }
--------------------------------------------------------------------------------
/src-tauri/gen/android/buildSrc/src/main/java/com/follow/app/kotlin/RustPlugin.kt:
--------------------------------------------------------------------------------
1 | import com.android.build.api.dsl.ApplicationExtension
2 | import org.gradle.api.DefaultTask
3 | import org.gradle.api.Plugin
4 | import org.gradle.api.Project
5 | import org.gradle.kotlin.dsl.configure
6 | import org.gradle.kotlin.dsl.get
7 |
8 | const val TASK_GROUP = "rust"
9 |
10 | open class Config {
11 | lateinit var rootDirRel: String
12 | }
13 |
14 | open class RustPlugin : Plugin {
15 | private lateinit var config: Config
16 |
17 | override fun apply(project: Project) = with(project) {
18 | config = extensions.create("rust", Config::class.java)
19 |
20 | val defaultAbiList = listOf("arm64-v8a", "armeabi-v7a", "x86", "x86_64");
21 | val abiList = (findProperty("abiList") as? String)?.split(',') ?: defaultAbiList
22 |
23 | val defaultArchList = listOf("arm64", "arm", "x86", "x86_64");
24 | val archList = (findProperty("archList") as? String)?.split(',') ?: defaultArchList
25 |
26 | val targetsList = (findProperty("targetList") as? String)?.split(',') ?: listOf("aarch64", "armv7", "i686", "x86_64")
27 |
28 | extensions.configure {
29 | @Suppress("UnstableApiUsage")
30 | flavorDimensions.add("abi")
31 | productFlavors {
32 | create("universal") {
33 | dimension = "abi"
34 | ndk {
35 | abiFilters += abiList
36 | }
37 | }
38 | defaultArchList.forEachIndexed { index, arch ->
39 | create(arch) {
40 | dimension = "abi"
41 | ndk {
42 | abiFilters.add(defaultAbiList[index])
43 | }
44 | }
45 | }
46 | }
47 | }
48 |
49 | afterEvaluate {
50 | for (profile in listOf("debug", "release")) {
51 | val profileCapitalized = profile.replaceFirstChar { it.uppercase() }
52 | val buildTask = tasks.maybeCreate(
53 | "rustBuildUniversal$profileCapitalized",
54 | DefaultTask::class.java
55 | ).apply {
56 | group = TASK_GROUP
57 | description = "Build dynamic library in $profile mode for all targets"
58 | }
59 |
60 | tasks["mergeUniversal${profileCapitalized}JniLibFolders"].dependsOn(buildTask)
61 |
62 | for (targetPair in targetsList.withIndex()) {
63 | val targetName = targetPair.value
64 | val targetArch = archList[targetPair.index]
65 | val targetArchCapitalized = targetArch.replaceFirstChar { it.uppercase() }
66 | val targetBuildTask = project.tasks.maybeCreate(
67 | "rustBuild$targetArchCapitalized$profileCapitalized",
68 | BuildTask::class.java
69 | ).apply {
70 | group = TASK_GROUP
71 | description = "Build dynamic library in $profile mode for $targetArch"
72 | rootDirRel = config.rootDirRel
73 | target = targetName
74 | release = profile == "release"
75 | }
76 |
77 | buildTask.dependsOn(targetBuildTask)
78 | tasks["merge$targetArchCapitalized${profileCapitalized}JniLibFolders"].dependsOn(
79 | targetBuildTask
80 | )
81 | }
82 | }
83 | }
84 | }
85 | }
--------------------------------------------------------------------------------
/src-tauri/gen/android/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 | # IDE (e.g. Android Studio) users:
3 | # Gradle settings configured through the IDE *will override*
4 | # any settings specified in this file.
5 | # For more details on how to configure your build environment visit
6 | # http://www.gradle.org/docs/current/userguide/build_environment.html
7 | # Specifies the JVM arguments used for the daemon process.
8 | # The setting is particularly useful for tweaking memory settings.
9 | org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
10 | # When configured, Gradle will run in incubating parallel mode.
11 | # This option should only be used with decoupled projects. More details, visit
12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
13 | # org.gradle.parallel=true
14 | # AndroidX package structure to make it clearer which packages are bundled with the
15 | # Android operating system, and which are packaged with your app"s APK
16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn
17 | android.useAndroidX=true
18 | # Kotlin code style for this project: "official" or "obsolete":
19 | kotlin.code.style=official
20 | # Enables namespacing of each library's R class so that its R class includes only the
21 | # resources declared in the library itself and none from the library's dependencies,
22 | # thereby reducing the size of the R class for that library
23 | android.nonTransitiveRClass=true
24 | android.nonFinalResIds=false
--------------------------------------------------------------------------------
/src-tauri/gen/android/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/moreoronce/followforandroid/2be607b61ae24aa5d475a01463fd7a546c57f9c5/src-tauri/gen/android/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/src-tauri/gen/android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Tue May 10 19:22:52 CST 2022
2 | distributionBase=GRADLE_USER_HOME
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip
4 | distributionPath=wrapper/dists
5 | zipStorePath=wrapper/dists
6 | zipStoreBase=GRADLE_USER_HOME
7 |
--------------------------------------------------------------------------------
/src-tauri/gen/android/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | #
4 | # Copyright 2015 the original author or authors.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | #
10 | # https://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | # See the License for the specific language governing permissions and
16 | # limitations under the License.
17 | #
18 |
19 | ##############################################################################
20 | ##
21 | ## Gradle start up script for UN*X
22 | ##
23 | ##############################################################################
24 |
25 | # Attempt to set APP_HOME
26 | # Resolve links: $0 may be a link
27 | PRG="$0"
28 | # Need this for relative symlinks.
29 | while [ -h "$PRG" ] ; do
30 | ls=`ls -ld "$PRG"`
31 | link=`expr "$ls" : '.*-> \(.*\)$'`
32 | if expr "$link" : '/.*' > /dev/null; then
33 | PRG="$link"
34 | else
35 | PRG=`dirname "$PRG"`"/$link"
36 | fi
37 | done
38 | SAVED="`pwd`"
39 | cd "`dirname \"$PRG\"`/" >/dev/null
40 | APP_HOME="`pwd -P`"
41 | cd "$SAVED" >/dev/null
42 |
43 | APP_NAME="Gradle"
44 | APP_BASE_NAME=`basename "$0"`
45 |
46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
48 |
49 | # Use the maximum available, or set MAX_FD != -1 to use that value.
50 | MAX_FD="maximum"
51 |
52 | warn () {
53 | echo "$*"
54 | }
55 |
56 | die () {
57 | echo
58 | echo "$*"
59 | echo
60 | exit 1
61 | }
62 |
63 | # OS specific support (must be 'true' or 'false').
64 | cygwin=false
65 | msys=false
66 | darwin=false
67 | nonstop=false
68 | case "`uname`" in
69 | CYGWIN* )
70 | cygwin=true
71 | ;;
72 | Darwin* )
73 | darwin=true
74 | ;;
75 | MINGW* )
76 | msys=true
77 | ;;
78 | NONSTOP* )
79 | nonstop=true
80 | ;;
81 | esac
82 |
83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
84 |
85 |
86 | # Determine the Java command to use to start the JVM.
87 | if [ -n "$JAVA_HOME" ] ; then
88 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
89 | # IBM's JDK on AIX uses strange locations for the executables
90 | JAVACMD="$JAVA_HOME/jre/sh/java"
91 | else
92 | JAVACMD="$JAVA_HOME/bin/java"
93 | fi
94 | if [ ! -x "$JAVACMD" ] ; then
95 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
96 |
97 | Please set the JAVA_HOME variable in your environment to match the
98 | location of your Java installation."
99 | fi
100 | else
101 | JAVACMD="java"
102 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
103 |
104 | Please set the JAVA_HOME variable in your environment to match the
105 | location of your Java installation."
106 | fi
107 |
108 | # Increase the maximum file descriptors if we can.
109 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
110 | MAX_FD_LIMIT=`ulimit -H -n`
111 | if [ $? -eq 0 ] ; then
112 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
113 | MAX_FD="$MAX_FD_LIMIT"
114 | fi
115 | ulimit -n $MAX_FD
116 | if [ $? -ne 0 ] ; then
117 | warn "Could not set maximum file descriptor limit: $MAX_FD"
118 | fi
119 | else
120 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
121 | fi
122 | fi
123 |
124 | # For Darwin, add options to specify how the application appears in the dock
125 | if $darwin; then
126 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
127 | fi
128 |
129 | # For Cygwin or MSYS, switch paths to Windows format before running java
130 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
131 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
132 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
133 |
134 | JAVACMD=`cygpath --unix "$JAVACMD"`
135 |
136 | # We build the pattern for arguments to be converted via cygpath
137 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
138 | SEP=""
139 | for dir in $ROOTDIRSRAW ; do
140 | ROOTDIRS="$ROOTDIRS$SEP$dir"
141 | SEP="|"
142 | done
143 | OURCYGPATTERN="(^($ROOTDIRS))"
144 | # Add a user-defined pattern to the cygpath arguments
145 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
146 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
147 | fi
148 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
149 | i=0
150 | for arg in "$@" ; do
151 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
152 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
153 |
154 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
155 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
156 | else
157 | eval `echo args$i`="\"$arg\""
158 | fi
159 | i=`expr $i + 1`
160 | done
161 | case $i in
162 | 0) set -- ;;
163 | 1) set -- "$args0" ;;
164 | 2) set -- "$args0" "$args1" ;;
165 | 3) set -- "$args0" "$args1" "$args2" ;;
166 | 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
167 | 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
168 | 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
169 | 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
170 | 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
171 | 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
172 | esac
173 | fi
174 |
175 | # Escape application args
176 | save () {
177 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
178 | echo " "
179 | }
180 | APP_ARGS=`save "$@"`
181 |
182 | # Collect all arguments for the java command, following the shell quoting and substitution rules
183 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
184 |
185 | exec "$JAVACMD" "$@"
186 |
--------------------------------------------------------------------------------
/src-tauri/gen/android/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 |
17 | @if "%DEBUG%" == "" @echo off
18 | @rem ##########################################################################
19 | @rem
20 | @rem Gradle startup script for Windows
21 | @rem
22 | @rem ##########################################################################
23 |
24 | @rem Set local scope for the variables with windows NT shell
25 | if "%OS%"=="Windows_NT" setlocal
26 |
27 | set DIRNAME=%~dp0
28 | if "%DIRNAME%" == "" set DIRNAME=.
29 | set APP_BASE_NAME=%~n0
30 | set APP_HOME=%DIRNAME%
31 |
32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
34 |
35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
37 |
38 | @rem Find java.exe
39 | if defined JAVA_HOME goto findJavaFromJavaHome
40 |
41 | set JAVA_EXE=java.exe
42 | %JAVA_EXE% -version >NUL 2>&1
43 | if "%ERRORLEVEL%" == "0" goto execute
44 |
45 | echo.
46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
47 | echo.
48 | echo Please set the JAVA_HOME variable in your environment to match the
49 | echo location of your Java installation.
50 |
51 | goto fail
52 |
53 | :findJavaFromJavaHome
54 | set JAVA_HOME=%JAVA_HOME:"=%
55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
56 |
57 | if exist "%JAVA_EXE%" goto execute
58 |
59 | echo.
60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
61 | echo.
62 | echo Please set the JAVA_HOME variable in your environment to match the
63 | echo location of your Java installation.
64 |
65 | goto fail
66 |
67 | :execute
68 | @rem Setup the command line
69 |
70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
71 |
72 |
73 | @rem Execute Gradle
74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
75 |
76 | :end
77 | @rem End local scope for the variables with windows NT shell
78 | if "%ERRORLEVEL%"=="0" goto mainEnd
79 |
80 | :fail
81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
82 | rem the _cmd.exe /c_ return code!
83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
84 | exit /b 1
85 |
86 | :mainEnd
87 | if "%OS%"=="Windows_NT" endlocal
88 |
89 | :omega
90 |
--------------------------------------------------------------------------------
/src-tauri/gen/android/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
3 | apply from: 'tauri.settings.gradle'
4 |
--------------------------------------------------------------------------------
/src-tauri/icons/128x128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/moreoronce/followforandroid/2be607b61ae24aa5d475a01463fd7a546c57f9c5/src-tauri/icons/128x128.png
--------------------------------------------------------------------------------
/src-tauri/icons/128x128@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/moreoronce/followforandroid/2be607b61ae24aa5d475a01463fd7a546c57f9c5/src-tauri/icons/128x128@2x.png
--------------------------------------------------------------------------------
/src-tauri/icons/32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/moreoronce/followforandroid/2be607b61ae24aa5d475a01463fd7a546c57f9c5/src-tauri/icons/32x32.png
--------------------------------------------------------------------------------
/src-tauri/icons/Square107x107Logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/moreoronce/followforandroid/2be607b61ae24aa5d475a01463fd7a546c57f9c5/src-tauri/icons/Square107x107Logo.png
--------------------------------------------------------------------------------
/src-tauri/icons/Square142x142Logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/moreoronce/followforandroid/2be607b61ae24aa5d475a01463fd7a546c57f9c5/src-tauri/icons/Square142x142Logo.png
--------------------------------------------------------------------------------
/src-tauri/icons/Square150x150Logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/moreoronce/followforandroid/2be607b61ae24aa5d475a01463fd7a546c57f9c5/src-tauri/icons/Square150x150Logo.png
--------------------------------------------------------------------------------
/src-tauri/icons/Square284x284Logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/moreoronce/followforandroid/2be607b61ae24aa5d475a01463fd7a546c57f9c5/src-tauri/icons/Square284x284Logo.png
--------------------------------------------------------------------------------
/src-tauri/icons/Square30x30Logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/moreoronce/followforandroid/2be607b61ae24aa5d475a01463fd7a546c57f9c5/src-tauri/icons/Square30x30Logo.png
--------------------------------------------------------------------------------
/src-tauri/icons/Square310x310Logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/moreoronce/followforandroid/2be607b61ae24aa5d475a01463fd7a546c57f9c5/src-tauri/icons/Square310x310Logo.png
--------------------------------------------------------------------------------
/src-tauri/icons/Square44x44Logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/moreoronce/followforandroid/2be607b61ae24aa5d475a01463fd7a546c57f9c5/src-tauri/icons/Square44x44Logo.png
--------------------------------------------------------------------------------
/src-tauri/icons/Square71x71Logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/moreoronce/followforandroid/2be607b61ae24aa5d475a01463fd7a546c57f9c5/src-tauri/icons/Square71x71Logo.png
--------------------------------------------------------------------------------
/src-tauri/icons/Square89x89Logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/moreoronce/followforandroid/2be607b61ae24aa5d475a01463fd7a546c57f9c5/src-tauri/icons/Square89x89Logo.png
--------------------------------------------------------------------------------
/src-tauri/icons/StoreLogo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/moreoronce/followforandroid/2be607b61ae24aa5d475a01463fd7a546c57f9c5/src-tauri/icons/StoreLogo.png
--------------------------------------------------------------------------------
/src-tauri/icons/icon.icns:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/moreoronce/followforandroid/2be607b61ae24aa5d475a01463fd7a546c57f9c5/src-tauri/icons/icon.icns
--------------------------------------------------------------------------------
/src-tauri/icons/icon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/moreoronce/followforandroid/2be607b61ae24aa5d475a01463fd7a546c57f9c5/src-tauri/icons/icon.ico
--------------------------------------------------------------------------------
/src-tauri/icons/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/moreoronce/followforandroid/2be607b61ae24aa5d475a01463fd7a546c57f9c5/src-tauri/icons/icon.png
--------------------------------------------------------------------------------
/src-tauri/icons/ios/AppIcon-20x20@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/moreoronce/followforandroid/2be607b61ae24aa5d475a01463fd7a546c57f9c5/src-tauri/icons/ios/AppIcon-20x20@1x.png
--------------------------------------------------------------------------------
/src-tauri/icons/ios/AppIcon-20x20@2x-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/moreoronce/followforandroid/2be607b61ae24aa5d475a01463fd7a546c57f9c5/src-tauri/icons/ios/AppIcon-20x20@2x-1.png
--------------------------------------------------------------------------------
/src-tauri/icons/ios/AppIcon-20x20@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/moreoronce/followforandroid/2be607b61ae24aa5d475a01463fd7a546c57f9c5/src-tauri/icons/ios/AppIcon-20x20@2x.png
--------------------------------------------------------------------------------
/src-tauri/icons/ios/AppIcon-20x20@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/moreoronce/followforandroid/2be607b61ae24aa5d475a01463fd7a546c57f9c5/src-tauri/icons/ios/AppIcon-20x20@3x.png
--------------------------------------------------------------------------------
/src-tauri/icons/ios/AppIcon-29x29@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/moreoronce/followforandroid/2be607b61ae24aa5d475a01463fd7a546c57f9c5/src-tauri/icons/ios/AppIcon-29x29@1x.png
--------------------------------------------------------------------------------
/src-tauri/icons/ios/AppIcon-29x29@2x-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/moreoronce/followforandroid/2be607b61ae24aa5d475a01463fd7a546c57f9c5/src-tauri/icons/ios/AppIcon-29x29@2x-1.png
--------------------------------------------------------------------------------
/src-tauri/icons/ios/AppIcon-29x29@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/moreoronce/followforandroid/2be607b61ae24aa5d475a01463fd7a546c57f9c5/src-tauri/icons/ios/AppIcon-29x29@2x.png
--------------------------------------------------------------------------------
/src-tauri/icons/ios/AppIcon-29x29@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/moreoronce/followforandroid/2be607b61ae24aa5d475a01463fd7a546c57f9c5/src-tauri/icons/ios/AppIcon-29x29@3x.png
--------------------------------------------------------------------------------
/src-tauri/icons/ios/AppIcon-40x40@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/moreoronce/followforandroid/2be607b61ae24aa5d475a01463fd7a546c57f9c5/src-tauri/icons/ios/AppIcon-40x40@1x.png
--------------------------------------------------------------------------------
/src-tauri/icons/ios/AppIcon-40x40@2x-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/moreoronce/followforandroid/2be607b61ae24aa5d475a01463fd7a546c57f9c5/src-tauri/icons/ios/AppIcon-40x40@2x-1.png
--------------------------------------------------------------------------------
/src-tauri/icons/ios/AppIcon-40x40@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/moreoronce/followforandroid/2be607b61ae24aa5d475a01463fd7a546c57f9c5/src-tauri/icons/ios/AppIcon-40x40@2x.png
--------------------------------------------------------------------------------
/src-tauri/icons/ios/AppIcon-40x40@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/moreoronce/followforandroid/2be607b61ae24aa5d475a01463fd7a546c57f9c5/src-tauri/icons/ios/AppIcon-40x40@3x.png
--------------------------------------------------------------------------------
/src-tauri/icons/ios/AppIcon-512@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/moreoronce/followforandroid/2be607b61ae24aa5d475a01463fd7a546c57f9c5/src-tauri/icons/ios/AppIcon-512@2x.png
--------------------------------------------------------------------------------
/src-tauri/icons/ios/AppIcon-60x60@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/moreoronce/followforandroid/2be607b61ae24aa5d475a01463fd7a546c57f9c5/src-tauri/icons/ios/AppIcon-60x60@2x.png
--------------------------------------------------------------------------------
/src-tauri/icons/ios/AppIcon-60x60@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/moreoronce/followforandroid/2be607b61ae24aa5d475a01463fd7a546c57f9c5/src-tauri/icons/ios/AppIcon-60x60@3x.png
--------------------------------------------------------------------------------
/src-tauri/icons/ios/AppIcon-76x76@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/moreoronce/followforandroid/2be607b61ae24aa5d475a01463fd7a546c57f9c5/src-tauri/icons/ios/AppIcon-76x76@1x.png
--------------------------------------------------------------------------------
/src-tauri/icons/ios/AppIcon-76x76@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/moreoronce/followforandroid/2be607b61ae24aa5d475a01463fd7a546c57f9c5/src-tauri/icons/ios/AppIcon-76x76@2x.png
--------------------------------------------------------------------------------
/src-tauri/icons/ios/AppIcon-83.5x83.5@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/moreoronce/followforandroid/2be607b61ae24aa5d475a01463fd7a546c57f9c5/src-tauri/icons/ios/AppIcon-83.5x83.5@2x.png
--------------------------------------------------------------------------------
/src-tauri/src/lib.rs:
--------------------------------------------------------------------------------
1 | // Learn more about Tauri commands at https://tauri.app/develop/calling-rust/
2 | #[tauri::command]
3 | fn greet(name: &str) -> String {
4 | format!("Hello, {}! You've been greeted from Rust!", name)
5 | }
6 |
7 | #[cfg_attr(mobile, tauri::mobile_entry_point)]
8 | pub fn run() {
9 | tauri::Builder::default()
10 | .plugin(tauri_plugin_opener::init())
11 | .invoke_handler(tauri::generate_handler![greet])
12 | .run(tauri::generate_context!())
13 | .expect("error while running tauri application");
14 | }
15 |
--------------------------------------------------------------------------------
/src-tauri/src/main.rs:
--------------------------------------------------------------------------------
1 | // Prevents additional console window on Windows in release, DO NOT REMOVE!!
2 | #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
3 |
4 | fn main() {
5 | follow_lib::run()
6 | }
7 |
--------------------------------------------------------------------------------
/src-tauri/tauri.conf.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://schema.tauri.app/config/2",
3 | "productName": "follow",
4 | "version": "0.1.2",
5 | "identifier": "com.follow.app",
6 | "build": {
7 | "beforeDevCommand": "bun run dev",
8 | "devUrl": "http://localhost:1420",
9 | "beforeBuildCommand": "bun run build",
10 | "frontendDist": "../dist"
11 | },
12 | "app": {
13 | "windows": [
14 | {
15 | "title": "follow",
16 | "decorations": false,
17 | "width": 1280,
18 | "height": 800,
19 | "resizable": true,
20 | "fullscreen": false,
21 | "url": "https://app.follow.is",
22 | "userAgent": "Mozilla/5.0 (Linux; Android 10; Mobile) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Mobile Safari/537.36"
23 | }
24 | ],
25 | "security": {
26 | "csp": "default-src 'self' https://app.follow.is; connect-src 'self' https://app.follow.is; img-src 'self' https://app.follow.is data:; script-src 'self' https://app.follow.is; style-src 'self' https://app.follow.is 'unsafe-inline';"
27 | }
28 | },
29 | "bundle": {
30 | "active": true,
31 | "targets": "all",
32 | "icon": [
33 | "icons/128x128.png",
34 | "icons/icon.png"
35 | ]
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/App.css:
--------------------------------------------------------------------------------
1 | .logo.vite:hover {
2 | filter: drop-shadow(0 0 2em #747bff);
3 | }
4 |
5 | .logo.react:hover {
6 | filter: drop-shadow(0 0 2em #61dafb);
7 | }
8 | :root {
9 | font-family: Inter, Avenir, Helvetica, Arial, sans-serif;
10 | font-size: 16px;
11 | line-height: 24px;
12 | font-weight: 400;
13 |
14 | color: #0f0f0f;
15 | background-color: #f6f6f6;
16 |
17 | font-synthesis: none;
18 | text-rendering: optimizeLegibility;
19 | -webkit-font-smoothing: antialiased;
20 | -moz-osx-font-smoothing: grayscale;
21 | -webkit-text-size-adjust: 100%;
22 | }
23 |
24 | .container {
25 | margin: 0;
26 | padding-top: 10vh;
27 | display: flex;
28 | flex-direction: column;
29 | justify-content: center;
30 | text-align: center;
31 | }
32 |
33 | .logo {
34 | height: 6em;
35 | padding: 1.5em;
36 | will-change: filter;
37 | transition: 0.75s;
38 | }
39 |
40 | .logo.tauri:hover {
41 | filter: drop-shadow(0 0 2em #24c8db);
42 | }
43 |
44 | .row {
45 | display: flex;
46 | justify-content: center;
47 | }
48 |
49 | a {
50 | font-weight: 500;
51 | color: #646cff;
52 | text-decoration: inherit;
53 | }
54 |
55 | a:hover {
56 | color: #535bf2;
57 | }
58 |
59 | h1 {
60 | text-align: center;
61 | }
62 |
63 | input,
64 | button {
65 | border-radius: 8px;
66 | border: 1px solid transparent;
67 | padding: 0.6em 1.2em;
68 | font-size: 1em;
69 | font-weight: 500;
70 | font-family: inherit;
71 | color: #0f0f0f;
72 | background-color: #ffffff;
73 | transition: border-color 0.25s;
74 | box-shadow: 0 2px 2px rgba(0, 0, 0, 0.2);
75 | }
76 |
77 | button {
78 | cursor: pointer;
79 | }
80 |
81 | button:hover {
82 | border-color: #396cd8;
83 | }
84 | button:active {
85 | border-color: #396cd8;
86 | background-color: #e8e8e8;
87 | }
88 |
89 | input,
90 | button {
91 | outline: none;
92 | }
93 |
94 | #greet-input {
95 | margin-right: 5px;
96 | }
97 |
98 | @media (prefers-color-scheme: dark) {
99 | :root {
100 | color: #f6f6f6;
101 | background-color: #2f2f2f;
102 | }
103 |
104 | a:hover {
105 | color: #24c8db;
106 | }
107 |
108 | input,
109 | button {
110 | color: #ffffff;
111 | background-color: #0f0f0f98;
112 | }
113 | button:active {
114 | background-color: #0f0f0f69;
115 | }
116 | }
117 |
--------------------------------------------------------------------------------
/src/App.tsx:
--------------------------------------------------------------------------------
1 | import { useState, useEffect } from "react";
2 | import reactLogo from "./assets/react.svg";
3 | import { invoke } from "@tauri-apps/api/core";
4 | import "./App.css";
5 |
6 | function registerServiceWorker() {
7 | if ("serviceWorker" in navigator) {
8 | window.addEventListener("load", () => {
9 | navigator.serviceWorker
10 | .register("/sw.js")
11 | .then(() => {
12 | console.log("ServiceWorker registration successful");
13 | })
14 | .catch((err) => {
15 | console.log("ServiceWorker registration failed: ", err);
16 | });
17 | });
18 | }
19 | }
20 |
21 | function App() {
22 | useEffect(() => {
23 | registerServiceWorker();
24 | }, []);
25 |
26 | const [greetMsg, setGreetMsg] = useState("");
27 | const [name, setName] = useState("");
28 |
29 | async function greet() {
30 | // Learn more about Tauri commands at https://tauri.app/develop/calling-rust/
31 | setGreetMsg(await invoke("greet", { name }));
32 | }
33 |
34 | return (
35 |
36 | Welcome to Tauri + React
37 |
38 |
49 | Click on the Tauri, Vite, and React logos to learn more.
50 |
51 |
65 | {greetMsg}
66 |
67 | );
68 | }
69 |
70 | export default App;
71 |
--------------------------------------------------------------------------------
/src/assets/react.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/main.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import ReactDOM from "react-dom/client";
3 | import App from "./App";
4 |
5 | ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render(
6 |
7 |
8 | ,
9 | );
10 |
--------------------------------------------------------------------------------
/src/sw.js:
--------------------------------------------------------------------------------
1 | const CACHE_NAME = "follow-cache-v1";
2 | const ASSETS = [
3 | "/",
4 | "/index.html",
5 | "/assets/**/*",
6 | "https://app.follow.is/**/*"
7 | ];
8 |
9 | // 添加调试日志
10 | console.log('[Service Worker] Installing...');
11 |
12 | self.addEventListener("install", (event) => {
13 | event.waitUntil(
14 | caches.open(CACHE_NAME).then((cache) => {
15 | return cache.addAll(ASSETS);
16 | })
17 | );
18 | });
19 |
20 | self.addEventListener("fetch", (event) => {
21 | console.log(`[Service Worker] Fetching: ${event.request.url}`);
22 |
23 | event.respondWith(
24 | caches.match(event.request).then((response) => {
25 | if (response) {
26 | console.log(`[Service Worker] Serving from cache: ${event.request.url}`);
27 | return response;
28 | }
29 |
30 | console.log(`[Service Worker] Fetching from network: ${event.request.url}`);
31 | return fetch(event.request)
32 | .then((networkResponse) => {
33 | // 缓存新的响应
34 | return caches.open(CACHE_NAME).then((cache) => {
35 | cache.put(event.request, networkResponse.clone());
36 | return networkResponse;
37 | });
38 | })
39 | .catch((error) => {
40 | console.error(`[Service Worker] Network request failed: ${error.message}`);
41 | // 回退到缓存中的旧响应
42 | return caches.match(event.request).then((cachedResponse) => {
43 | if (cachedResponse) {
44 | console.log(`[Service Worker] Serving fallback from cache: ${event.request.url}`);
45 | return cachedResponse;
46 | }
47 | throw error; // 如果没有缓存,抛出错误
48 | });
49 | });
50 | })
51 | );
52 | });
53 |
54 | self.addEventListener("activate", (event) => {
55 | event.waitUntil(
56 | caches.keys().then((cacheNames) => {
57 | return Promise.all(
58 | cacheNames
59 | .filter((name) => name !== CACHE_NAME)
60 | .map((name) => caches.delete(name))
61 | );
62 | })
63 | );
64 | });
--------------------------------------------------------------------------------
/src/vite-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ES2020",
4 | "useDefineForClassFields": true,
5 | "lib": ["ES2020", "DOM", "DOM.Iterable"],
6 | "module": "ESNext",
7 | "skipLibCheck": true,
8 |
9 | /* Bundler mode */
10 | "moduleResolution": "bundler",
11 | "allowImportingTsExtensions": true,
12 | "resolveJsonModule": true,
13 | "isolatedModules": true,
14 | "noEmit": true,
15 | "jsx": "react-jsx",
16 |
17 | /* Linting */
18 | "strict": true,
19 | "noUnusedLocals": true,
20 | "noUnusedParameters": true,
21 | "noFallthroughCasesInSwitch": true
22 | },
23 | "include": ["src"],
24 | "references": [{ "path": "./tsconfig.node.json" }]
25 | }
26 |
--------------------------------------------------------------------------------
/tsconfig.node.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "composite": true,
4 | "skipLibCheck": true,
5 | "module": "ESNext",
6 | "moduleResolution": "bundler",
7 | "allowSyntheticDefaultImports": true
8 | },
9 | "include": ["vite.config.ts"]
10 | }
11 |
--------------------------------------------------------------------------------
/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from "vite";
2 | import react from "@vitejs/plugin-react";
3 | import { VitePWA } from "vite-plugin-pwa";
4 |
5 | // @ts-expect-error process is a nodejs global
6 | const host = process.env.TAURI_DEV_HOST;
7 |
8 | // https://vitejs.dev/config/
9 | export default defineConfig(async () => ({
10 | plugins: [
11 | react(),
12 | VitePWA({
13 | registerType: "autoUpdate",
14 | manifest: false,
15 | workbox: {
16 | globPatterns: ["**/*.{js,css,html,ico,png,svg}"],
17 | runtimeCaching: [
18 | {
19 | urlPattern: /^https:\/\/app\.follow\.is\/.*/i,
20 | handler: "NetworkFirst",
21 | options: {
22 | cacheName: "follow-cache",
23 | expiration: {
24 | maxEntries: 100,
25 | maxAgeSeconds: 60 * 60 * 24 * 30, // 30 days
26 | },
27 | cacheableResponse: {
28 | statuses: [0, 200],
29 | },
30 | networkTimeoutSeconds: 3, // 回退到缓存前的网络超时时间
31 | },
32 | },
33 | ],
34 | },
35 | }),
36 | ],
37 |
38 | build: {
39 | rollupOptions: {
40 | output: {
41 | manualChunks: {
42 | vendor: ["react", "react-dom"],
43 | },
44 | },
45 | },
46 | },
47 |
48 | // Vite options tailored for Tauri development and only applied in `tauri dev` or `tauri build`
49 | //
50 | // 1. prevent vite from obscuring rust errors
51 | clearScreen: false,
52 | // 2. tauri expects a fixed port, fail if that port is not available
53 | server: {
54 | port: 1420,
55 | strictPort: true,
56 | host: host || false,
57 | hmr: host
58 | ? {
59 | protocol: "ws",
60 | host,
61 | port: 1421,
62 | }
63 | : undefined,
64 | watch: {
65 | // 3. tell vite to ignore watching `src-tauri`
66 | ignored: ["**/src-tauri/**"],
67 | },
68 | },
69 | }));
70 |
--------------------------------------------------------------------------------