mirror of
https://github.com/KRTirtho/spotube.git
synced 2025-09-13 16:05:18 +00:00
Merge branch 'master' into dev
This commit is contained in:
commit
8fe9e4d245
@ -1,3 +1,7 @@
|
|||||||
POCKETBASE_URL=
|
POCKETBASE_URL=
|
||||||
USERNAME=
|
USERNAME=
|
||||||
PASSWORD=
|
PASSWORD=
|
||||||
|
|
||||||
|
# The format:
|
||||||
|
# SPOTIFY_SECRETS=clintId1:clientSecret1,clientId2:clientSecret2
|
||||||
|
SPOTIFY_SECRETS=
|
12
.github/workflows/spotube-release-binary.yml
vendored
12
.github/workflows/spotube-release-binary.yml
vendored
@ -61,7 +61,7 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
flutter config --enable-windows-desktop
|
flutter config --enable-windows-desktop
|
||||||
flutter pub get
|
flutter pub get
|
||||||
dart bin/create-secrets.dart '${{ secrets.LYRICS_SECRET }}' '${{ secrets.SPOTIFY_SECRET }}'
|
flutter pub run build_runner build --delete-conflicting-outputs
|
||||||
|
|
||||||
- name: Build Windows Executable
|
- name: Build Windows Executable
|
||||||
run: |
|
run: |
|
||||||
@ -99,7 +99,7 @@ jobs:
|
|||||||
- name: Install Dependencies
|
- name: Install Dependencies
|
||||||
run: |
|
run: |
|
||||||
sudo apt-get update -y
|
sudo apt-get update -y
|
||||||
sudo apt-get install -y tar clang cmake ninja-build pkg-config libgtk-3-dev make python3-pip python3-setuptools patchelf desktop-file-utils libgdk-pixbuf2.0-dev fakeroot strace fuse libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libunwind-dev locate patchelf gir1.2-appindicator3-0.1 libappindicator3-1 libappindicator3-dev libsecret-1-0 libjsoncpp1 libsecret-1-dev libjsoncpp-dev
|
sudo apt-get install -y tar clang cmake ninja-build pkg-config libgtk-3-dev make python3-pip python3-setuptools desktop-file-utils libgdk-pixbuf2.0-dev fakeroot strace fuse libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libunwind-dev locate patchelf gir1.2-appindicator3-0.1 libappindicator3-1 libappindicator3-dev libsecret-1-0 libjsoncpp1 libsecret-1-dev libjsoncpp-dev
|
||||||
|
|
||||||
- name: Install AppImage Tool
|
- name: Install AppImage Tool
|
||||||
run: |
|
run: |
|
||||||
@ -136,7 +136,7 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
flutter config --enable-linux-desktop
|
flutter config --enable-linux-desktop
|
||||||
flutter pub get
|
flutter pub get
|
||||||
dart bin/create-secrets.dart '${{ secrets.LYRICS_SECRET }}' '${{ secrets.SPOTIFY_SECRET }}'
|
flutter pub run build_runner build --delete-conflicting-outputs
|
||||||
|
|
||||||
- name: Build Linux Packages
|
- name: Build Linux Packages
|
||||||
run: |
|
run: |
|
||||||
@ -200,10 +200,10 @@ jobs:
|
|||||||
if: ${{ inputs.channel == 'nightly' }}
|
if: ${{ inputs.channel == 'nightly' }}
|
||||||
run: echo '${{ secrets.DOTENV_NIGHTLY }}' > .env
|
run: echo '${{ secrets.DOTENV_NIGHTLY }}' > .env
|
||||||
|
|
||||||
- name: Generate Secrets and Build apk
|
- name: Generate Secrets
|
||||||
run: |
|
run: |
|
||||||
flutter pub get
|
flutter pub get
|
||||||
dart bin/create-secrets.dart '${{ secrets.LYRICS_SECRET }}' '${{ secrets.SPOTIFY_SECRET }}'
|
flutter pub run build_runner build --delete-conflicting-outputs
|
||||||
|
|
||||||
- name: Sign Apk
|
- name: Sign Apk
|
||||||
run: |
|
run: |
|
||||||
@ -253,7 +253,7 @@ jobs:
|
|||||||
- name: Generate Secrets
|
- name: Generate Secrets
|
||||||
run: |
|
run: |
|
||||||
flutter pub get
|
flutter pub get
|
||||||
dart bin/create-secrets.dart '${{ secrets.LYRICS_SECRET }}' '${{ secrets.SPOTIFY_SECRET }}'
|
flutter pub run build_runner build --delete-conflicting-outputs
|
||||||
|
|
||||||
- name: Build Macos App
|
- name: Build Macos App
|
||||||
run: |
|
run: |
|
||||||
|
3
.gitignore
vendored
3
.gitignore
vendored
@ -66,9 +66,8 @@ installer.exe
|
|||||||
|
|
||||||
# secrets
|
# secrets
|
||||||
*.env
|
*.env
|
||||||
lib/models/generated_secrets.dart
|
lib/collections/env.g.dart
|
||||||
help.txt
|
help.txt
|
||||||
secrets.json
|
|
||||||
|
|
||||||
dist
|
dist
|
||||||
appimage-build
|
appimage-build
|
||||||
|
@ -120,38 +120,28 @@ Do the following:
|
|||||||
|
|
||||||
- Download the latest Flutter SDK (>=2.15.1) & enable desktop support
|
- Download the latest Flutter SDK (>=2.15.1) & enable desktop support
|
||||||
- Install Development dependencies in linux
|
- Install Development dependencies in linux
|
||||||
- `libappindicator3-1 gir1.2-appindicator3-0.1 libappindicator3-dev libsecret-1-0 libjsoncpp1 libsecret-1-dev libjsoncpp-dev libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev` (for Debian/Ubuntu)
|
- Debian/Ubuntu
|
||||||
- `libappindicator-gtk3 libsecret jsoncpp gstreamer gst-libav gst-plugins-base gst-plugins-good` (for Arch/Manjaro)
|
```bash
|
||||||
- `libappindicator libsecret libsecret-devel jsoncpp gstreamer1-devel gstreamer1-plugins-base-tools gstreamer1-doc gstreamer1-plugins-base-devel gstreamer1-plugins-good gstreamer1-plugins-good-extras` (for Fedora)
|
$ apt-get install libappindicator3-1 gir1.2-appindicator3-0.1 libappindicator3-dev libsecret-1-0 libjsoncpp1 libsecret-1-dev libjsoncpp-dev libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev
|
||||||
- Clone the Repo & Run `flutter pub get` in the Terminal
|
```
|
||||||
- Create a `secrets.json` in root of the project. The structure should be similar to the following example:
|
- Use `libjsoncpp25` instead of `libjsoncpp1` (for Ubuntu >= 22.04)
|
||||||
|
- Arch/Manjaro
|
||||||
```jsoc name="secrets.json"
|
```bash
|
||||||
{
|
yay -S libappindicator-gtk3 libsecret jsoncpp gstreamer gst-libav gst-plugins-base gst-plugins-good
|
||||||
"LYRICS_SECRET": [
|
```
|
||||||
"Bo3LQEMcL2xUAJ6yCfQowV6f8K78s9J9FLa67AsyWmvhkP9LWikkgcEyFrzvs7jsR",
|
- Fedora
|
||||||
"HiLHxLj8uv2VhBZfq9BQ9HVrWQk5Jc8aneMZX8RV4KjTmC387K692xrbNK35c8Qe4"
|
```bash
|
||||||
],
|
dnf install libappindicator libsecret libsecret-devel jsoncpp gstreamer1-devel gstreamer1-plugins-base-tools gstreamer1-doc gstreamer1-plugins-base-devel gstreamer1-plugins-good gstreamer1-plugins-good-extras
|
||||||
"SPOTIFY_SECRET": [
|
```
|
||||||
{
|
- Clone the Repo
|
||||||
"clientId": "9ed19daf-c7a2-4c28-91ac-2c5283ad86cf",
|
- Create a `.env` in root of the project following the `.env.example` template
|
||||||
"clientSecret": "236d5822-820e-457e-b18c-10e258c9386b"
|
- Now run the following to bootstrap the project
|
||||||
},
|
```bash
|
||||||
{
|
flutter pub get && flutter pub run build_runner build --delete-conflicting-outputs
|
||||||
"clientId": "b4769027-e048-4485-8f0b-b8a336f2cd97",
|
```
|
||||||
"clientSecret": "41df6ea4-eba2-4d42-b7be-6f727555fccc"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
> You can add more clientId/clientSecret/genius-access-token if you want. The credentials used in the example are dummy (fake). You've to use your own secrets
|
|
||||||
|
|
||||||
- Finally run these following commands in the root of the project to start the Spotube Locally
|
- Finally run these following commands in the root of the project to start the Spotube Locally
|
||||||
|
```bash
|
||||||
```bash
|
flutter run -d <window|macos|linux|(<android-device-id>)>
|
||||||
$ dart bin/create-secrets.dart --local
|
```
|
||||||
$ flutter run -d <window|macos|linux|(<android-device-id>)>
|
|
||||||
```
|
|
||||||
|
|
||||||
Do debugging/testing/build etc then submit to us with PR against the development branch (master) & we'll review your code
|
Do debugging/testing/build etc then submit to us with PR against the development branch (master) & we'll review your code
|
||||||
|
27
android/app/src/main/res/drawable/ic_launcher_monochrome.xml
Normal file
27
android/app/src/main/res/drawable/ic_launcher_monochrome.xml
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="108dp"
|
||||||
|
android:height="108dp"
|
||||||
|
android:viewportWidth="762"
|
||||||
|
android:viewportHeight="762">
|
||||||
|
<path
|
||||||
|
android:pathData="M309.08,370.99L309.08,479.87C309.08,486.36 314.33,491.6 320.83,491.6C327.31,491.6 332.58,486.36 332.58,479.87L332.58,370.99C332.58,364.51 327.31,359.26 320.83,359.26C314.33,359.26 309.08,364.51 309.08,370.99Z"
|
||||||
|
android:strokeLineJoin="miter"
|
||||||
|
android:strokeWidth="14"
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:strokeColor="#000000"
|
||||||
|
android:strokeLineCap="butt"/>
|
||||||
|
<path
|
||||||
|
android:pathData="M254.59,491.73L280.46,491.73L280.46,362.47C280.53,361.85 280.64,361.23 280.64,360.6C280.64,304.83 325.72,259.46 381.12,259.46C436.51,259.46 481.59,304.83 481.59,360.6C481.59,361.45 481.71,362.27 481.84,363.1L481.84,491.73L507.71,491.73C525.72,491.73 540.33,476.65 540.33,458.03L540.33,390.62C540.33,375.26 530.37,362.33 516.78,358.26C515.53,284.17 455.17,224.26 381.12,224.26C307.05,224.26 246.69,284.18 245.45,358.29C231.88,362.36 221.96,375.29 221.96,390.63L221.96,458.03C221.96,476.64 236.56,491.73 254.59,491.73Z"
|
||||||
|
android:strokeLineJoin="miter"
|
||||||
|
android:strokeWidth="20"
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:strokeColor="#000000"
|
||||||
|
android:strokeLineCap="butt"/>
|
||||||
|
<path
|
||||||
|
android:pathData="M431.08,370.99L431.08,479.87C431.08,486.36 436.33,491.6 442.83,491.6C449.31,491.6 454.58,486.36 454.58,479.87L454.58,370.99C454.58,364.51 449.31,359.26 442.83,359.26C436.33,359.26 431.08,364.51 431.08,370.99Z"
|
||||||
|
android:strokeLineJoin="miter"
|
||||||
|
android:strokeWidth="14"
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:strokeColor="#000000"
|
||||||
|
android:strokeLineCap="butt"/>
|
||||||
|
</vector>
|
@ -2,4 +2,5 @@
|
|||||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
<background android:drawable="@color/ic_launcher_background"/>
|
<background android:drawable="@color/ic_launcher_background"/>
|
||||||
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
|
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
|
||||||
|
<monochrome android:drawable="@drawable/ic_launcher_monochrome"/>
|
||||||
</adaptive-icon>
|
</adaptive-icon>
|
||||||
|
@ -1,177 +0,0 @@
|
|||||||
import 'dart:convert';
|
|
||||||
import 'dart:io';
|
|
||||||
|
|
||||||
import 'package:path/path.dart' as path;
|
|
||||||
|
|
||||||
// blob metadata for de-stringifying
|
|
||||||
const randHash = [
|
|
||||||
49,
|
|
||||||
111,
|
|
||||||
98,
|
|
||||||
72,
|
|
||||||
78,
|
|
||||||
122,
|
|
||||||
98,
|
|
||||||
48,
|
|
||||||
112,
|
|
||||||
73,
|
|
||||||
81,
|
|
||||||
50,
|
|
||||||
112,
|
|
||||||
89,
|
|
||||||
90,
|
|
||||||
50,
|
|
||||||
116,
|
|
||||||
83,
|
|
||||||
84,
|
|
||||||
110,
|
|
||||||
99,
|
|
||||||
105,
|
|
||||||
76,
|
|
||||||
67,
|
|
||||||
74,
|
|
||||||
67,
|
|
||||||
89,
|
|
||||||
121,
|
|
||||||
48,
|
|
||||||
119,
|
|
||||||
77,
|
|
||||||
106,
|
|
||||||
69,
|
|
||||||
50,
|
|
||||||
86,
|
|
||||||
69,
|
|
||||||
53,
|
|
||||||
107,
|
|
||||||
77,
|
|
||||||
69,
|
|
||||||
86,
|
|
||||||
71,
|
|
||||||
101,
|
|
||||||
68,
|
|
||||||
66,
|
|
||||||
113,
|
|
||||||
78,
|
|
||||||
110,
|
|
||||||
66,
|
|
||||||
119
|
|
||||||
];
|
|
||||||
const sugarCarbonator = [
|
|
||||||
81,
|
|
||||||
119,
|
|
||||||
79,
|
|
||||||
71,
|
|
||||||
85,
|
|
||||||
53,
|
|
||||||
78,
|
|
||||||
50,
|
|
||||||
69,
|
|
||||||
52,
|
|
||||||
90,
|
|
||||||
68,
|
|
||||||
107,
|
|
||||||
120,
|
|
||||||
77,
|
|
||||||
87,
|
|
||||||
89,
|
|
||||||
52,
|
|
||||||
89,
|
|
||||||
84,
|
|
||||||
73
|
|
||||||
];
|
|
||||||
const randomSalt = [
|
|
||||||
70,
|
|
||||||
117,
|
|
||||||
67,
|
|
||||||
75,
|
|
||||||
117,
|
|
||||||
116,
|
|
||||||
72,
|
|
||||||
101,
|
|
||||||
105,
|
|
||||||
102,
|
|
||||||
65,
|
|
||||||
110,
|
|
||||||
68,
|
|
||||||
87,
|
|
||||||
72,
|
|
||||||
97,
|
|
||||||
84,
|
|
||||||
85,
|
|
||||||
82,
|
|
||||||
100,
|
|
||||||
79,
|
|
||||||
73,
|
|
||||||
110,
|
|
||||||
103,
|
|
||||||
83,
|
|
||||||
117,
|
|
||||||
75,
|
|
||||||
115
|
|
||||||
];
|
|
||||||
const algorithmicSugar = [
|
|
||||||
70,
|
|
||||||
117,
|
|
||||||
67,
|
|
||||||
75,
|
|
||||||
117,
|
|
||||||
116,
|
|
||||||
72,
|
|
||||||
101,
|
|
||||||
105,
|
|
||||||
102,
|
|
||||||
65,
|
|
||||||
78,
|
|
||||||
100,
|
|
||||||
102,
|
|
||||||
68,
|
|
||||||
114,
|
|
||||||
79,
|
|
||||||
105,
|
|
||||||
100,
|
|
||||||
115,
|
|
||||||
85,
|
|
||||||
99,
|
|
||||||
107,
|
|
||||||
83
|
|
||||||
];
|
|
||||||
|
|
||||||
void main(List<String> args) async {
|
|
||||||
List<String> val;
|
|
||||||
List<Map> val2;
|
|
||||||
|
|
||||||
final cwd = Directory.current.path;
|
|
||||||
final binSafe = cwd.endsWith("/bin") ? ".." : "";
|
|
||||||
if (args.isEmpty) {
|
|
||||||
throw ArgumentError("Expected 1-3 arguments but passed none");
|
|
||||||
}
|
|
||||||
if (args.contains("--local")) {
|
|
||||||
final secretFilePath = path.join(cwd, binSafe, "secrets.json");
|
|
||||||
final file = File(secretFilePath);
|
|
||||||
if (!file.existsSync()) throw Exception("secrets.json file not found");
|
|
||||||
final data = jsonDecode(await file.readAsString());
|
|
||||||
val = List.castFrom<dynamic, String>(data["LYRICS_SECRET"]);
|
|
||||||
val2 = List.castFrom<dynamic, Map>(data["SPOTIFY_SECRET"]);
|
|
||||||
} else if (args.contains("--fdroid")) {
|
|
||||||
final decodedLyricSecret = utf8.decode(base64Decode(
|
|
||||||
args[1].replaceAll(
|
|
||||||
String.fromCharCodes(randomSalt), String.fromCharCodes(randHash)),
|
|
||||||
));
|
|
||||||
final decodedSpotifySecret = utf8.decode(base64Decode(
|
|
||||||
args.last.replaceAll(String.fromCharCodes(algorithmicSugar),
|
|
||||||
String.fromCharCodes(sugarCarbonator)),
|
|
||||||
));
|
|
||||||
val = List.castFrom<dynamic, String>(jsonDecode(decodedLyricSecret));
|
|
||||||
val2 = List.castFrom<dynamic, Map>(jsonDecode(decodedSpotifySecret));
|
|
||||||
} else {
|
|
||||||
final decodedLyricSecret = utf8.decode(base64Decode(args.first));
|
|
||||||
final decodedSpotifySecret = utf8.decode(base64Decode(args.last));
|
|
||||||
val = List.castFrom<dynamic, String>(jsonDecode(decodedLyricSecret));
|
|
||||||
val2 = List.castFrom<dynamic, Map>(jsonDecode(decodedSpotifySecret));
|
|
||||||
}
|
|
||||||
|
|
||||||
await File(path.join(cwd, binSafe, "lib/models/generated_secrets.dart"))
|
|
||||||
.writeAsString(
|
|
||||||
"final List<String> lyricsSecrets = ${jsonEncode(val)};\nfinal List<Map<String, dynamic>> spotifySecrets = ${jsonEncode(val2)};",
|
|
||||||
);
|
|
||||||
}
|
|
@ -5,11 +5,9 @@
|
|||||||
|
|
||||||
// coverage:ignore-file
|
// coverage:ignore-file
|
||||||
// ignore_for_file: type=lint
|
// ignore_for_file: type=lint
|
||||||
// ignore_for_file: directives_ordering,unnecessary_import,implicit_dynamic_list_literal
|
// ignore_for_file: directives_ordering,unnecessary_import,implicit_dynamic_list_literal,deprecated_member_use
|
||||||
|
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
import 'package:flutter_svg/flutter_svg.dart';
|
|
||||||
import 'package:flutter/services.dart';
|
|
||||||
|
|
||||||
class $AssetsTutorialGen {
|
class $AssetsTutorialGen {
|
||||||
const $AssetsTutorialGen();
|
const $AssetsTutorialGen();
|
||||||
@ -39,8 +37,7 @@ class Assets {
|
|||||||
AssetGenImage('assets/spotube-logo-foreground.jpg');
|
AssetGenImage('assets/spotube-logo-foreground.jpg');
|
||||||
static const AssetGenImage spotubeLogoPng =
|
static const AssetGenImage spotubeLogoPng =
|
||||||
AssetGenImage('assets/spotube-logo.png');
|
AssetGenImage('assets/spotube-logo.png');
|
||||||
static const SvgGenImage spotubeLogoSvg =
|
static const String spotubeLogoSvg = 'assets/spotube-logo.svg';
|
||||||
SvgGenImage('assets/spotube-logo.svg');
|
|
||||||
static const AssetGenImage spotubeScreenshot =
|
static const AssetGenImage spotubeScreenshot =
|
||||||
AssetGenImage('assets/spotube-screenshot.jpg');
|
AssetGenImage('assets/spotube-screenshot.jpg');
|
||||||
static const AssetGenImage spotubeBanner =
|
static const AssetGenImage spotubeBanner =
|
||||||
@ -129,54 +126,3 @@ class AssetGenImage {
|
|||||||
|
|
||||||
String get keyName => _assetName;
|
String get keyName => _assetName;
|
||||||
}
|
}
|
||||||
|
|
||||||
class SvgGenImage {
|
|
||||||
const SvgGenImage(this._assetName);
|
|
||||||
|
|
||||||
final String _assetName;
|
|
||||||
|
|
||||||
SvgPicture svg({
|
|
||||||
Key? key,
|
|
||||||
bool matchTextDirection = false,
|
|
||||||
AssetBundle? bundle,
|
|
||||||
String? package,
|
|
||||||
double? width,
|
|
||||||
double? height,
|
|
||||||
BoxFit fit = BoxFit.contain,
|
|
||||||
AlignmentGeometry alignment = Alignment.center,
|
|
||||||
bool allowDrawingOutsideViewBox = false,
|
|
||||||
WidgetBuilder? placeholderBuilder,
|
|
||||||
Color? color,
|
|
||||||
BlendMode colorBlendMode = BlendMode.srcIn,
|
|
||||||
String? semanticsLabel,
|
|
||||||
bool excludeFromSemantics = false,
|
|
||||||
Clip clipBehavior = Clip.hardEdge,
|
|
||||||
bool cacheColorFilter = false,
|
|
||||||
SvgTheme? theme,
|
|
||||||
}) {
|
|
||||||
return SvgPicture.asset(
|
|
||||||
_assetName,
|
|
||||||
key: key,
|
|
||||||
matchTextDirection: matchTextDirection,
|
|
||||||
bundle: bundle,
|
|
||||||
package: package,
|
|
||||||
width: width,
|
|
||||||
height: height,
|
|
||||||
fit: fit,
|
|
||||||
alignment: alignment,
|
|
||||||
allowDrawingOutsideViewBox: allowDrawingOutsideViewBox,
|
|
||||||
placeholderBuilder: placeholderBuilder,
|
|
||||||
color: color,
|
|
||||||
colorBlendMode: colorBlendMode,
|
|
||||||
semanticsLabel: semanticsLabel,
|
|
||||||
excludeFromSemantics: excludeFromSemantics,
|
|
||||||
clipBehavior: clipBehavior,
|
|
||||||
cacheColorFilter: cacheColorFilter,
|
|
||||||
theme: theme,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
String get path => _assetName;
|
|
||||||
|
|
||||||
String get keyName => _assetName;
|
|
||||||
}
|
|
||||||
|
@ -1,17 +1,24 @@
|
|||||||
import 'package:flutter/foundation.dart';
|
import 'package:envied/envied.dart';
|
||||||
import 'package:flutter_dotenv/flutter_dotenv.dart';
|
|
||||||
|
|
||||||
|
part 'env.g.dart';
|
||||||
|
|
||||||
|
@Envied(obfuscate: true, requireEnvFile: true, path: ".env")
|
||||||
abstract class Env {
|
abstract class Env {
|
||||||
static final String pocketbaseUrl =
|
@EnviedField(varName: 'POCKETBASE_URL', defaultValue: 'http://127.0.0.1:8090')
|
||||||
dotenv.get('POCKETBASE_URL', fallback: 'http://127.0.0.1:8090');
|
static final pocketbaseUrl = _Env.pocketbaseUrl;
|
||||||
static final String username = dotenv.get('USERNAME', fallback: 'root');
|
|
||||||
static final String password = dotenv.get('PASSWORD', fallback: '12345678');
|
|
||||||
|
|
||||||
static configure() async {
|
@EnviedField(varName: 'USERNAME', defaultValue: 'root')
|
||||||
if (kReleaseMode) {
|
static final username = _Env.username;
|
||||||
await dotenv.load(fileName: ".env");
|
|
||||||
} else {
|
@EnviedField(varName: 'PASSWORD', defaultValue: '12345678')
|
||||||
dotenv.testLoad();
|
static final password = _Env.password;
|
||||||
}
|
|
||||||
}
|
@EnviedField(varName: 'SPOTIFY_SECRETS')
|
||||||
|
static final spotifySecrets = _Env.spotifySecrets.split(',').map((e) {
|
||||||
|
final secrets = e.trim().split(":").map((e) => e.trim());
|
||||||
|
return {
|
||||||
|
"clientId": secrets.first,
|
||||||
|
"clientSecret": secrets.last,
|
||||||
|
};
|
||||||
|
}).toList();
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,6 @@ import 'package:hooks_riverpod/hooks_riverpod.dart';
|
|||||||
import 'package:metadata_god/metadata_god.dart';
|
import 'package:metadata_god/metadata_god.dart';
|
||||||
import 'package:package_info_plus/package_info_plus.dart';
|
import 'package:package_info_plus/package_info_plus.dart';
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
import 'package:spotube/collections/env.dart';
|
|
||||||
import 'package:spotube/components/shared/dialogs/replace_downloaded_dialog.dart';
|
import 'package:spotube/components/shared/dialogs/replace_downloaded_dialog.dart';
|
||||||
import 'package:spotube/entities/cache_track.dart';
|
import 'package:spotube/entities/cache_track.dart';
|
||||||
import 'package:spotube/collections/routes.dart';
|
import 'package:spotube/collections/routes.dart';
|
||||||
@ -87,7 +86,6 @@ Future<void> main(List<String> rawArgs) async {
|
|||||||
Hive.registerAdapter(CacheTrackAdapter());
|
Hive.registerAdapter(CacheTrackAdapter());
|
||||||
Hive.registerAdapter(CacheTrackEngagementAdapter());
|
Hive.registerAdapter(CacheTrackEngagementAdapter());
|
||||||
Hive.registerAdapter(CacheTrackSkipSegmentAdapter());
|
Hive.registerAdapter(CacheTrackSkipSegmentAdapter());
|
||||||
await Env.configure();
|
|
||||||
|
|
||||||
Catcher(
|
Catcher(
|
||||||
enableLogger: arguments["verbose"],
|
enableLogger: arguments["verbose"],
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:spotify/spotify.dart';
|
import 'package:spotify/spotify.dart';
|
||||||
import 'package:spotube/models/generated_secrets.dart';
|
import 'package:spotube/collections/env.dart';
|
||||||
|
|
||||||
import 'package:spotube/provider/authentication_provider.dart';
|
import 'package:spotube/provider/authentication_provider.dart';
|
||||||
import 'package:spotube/utils/primitive_utils.dart';
|
import 'package:spotube/utils/primitive_utils.dart';
|
||||||
|
|
||||||
final spotifyProvider = Provider<SpotifyApi>((ref) {
|
final spotifyProvider = Provider<SpotifyApi>((ref) {
|
||||||
final authState = ref.watch(AuthenticationNotifier.provider);
|
final authState = ref.watch(AuthenticationNotifier.provider);
|
||||||
final anonCred = PrimitiveUtils.getRandomElement(spotifySecrets);
|
final anonCred = PrimitiveUtils.getRandomElement(Env.spotifySecrets);
|
||||||
|
|
||||||
if (authState == null) {
|
if (authState == null) {
|
||||||
return SpotifyApi(
|
return SpotifyApi(
|
||||||
|
@ -4,10 +4,9 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:path_provider/path_provider.dart';
|
import 'package:path_provider/path_provider.dart';
|
||||||
import 'package:spotube/components/settings/color_scheme_picker_dialog.dart';
|
import 'package:spotube/components/settings/color_scheme_picker_dialog.dart';
|
||||||
import 'package:spotube/models/generated_secrets.dart';
|
|
||||||
import 'package:spotube/utils/persisted_change_notifier.dart';
|
import 'package:spotube/utils/persisted_change_notifier.dart';
|
||||||
import 'package:spotube/utils/platform.dart';
|
import 'package:spotube/utils/platform.dart';
|
||||||
import 'package:spotube/utils/primitive_utils.dart';
|
|
||||||
import 'package:path/path.dart' as path;
|
import 'package:path/path.dart' as path;
|
||||||
|
|
||||||
enum LayoutMode {
|
enum LayoutMode {
|
||||||
@ -30,7 +29,6 @@ class UserPreferences extends PersistedChangeNotifier {
|
|||||||
ThemeMode themeMode;
|
ThemeMode themeMode;
|
||||||
String recommendationMarket;
|
String recommendationMarket;
|
||||||
bool saveTrackLyrics;
|
bool saveTrackLyrics;
|
||||||
String geniusAccessToken;
|
|
||||||
bool checkUpdate;
|
bool checkUpdate;
|
||||||
AudioQuality audioQuality;
|
AudioQuality audioQuality;
|
||||||
|
|
||||||
@ -48,7 +46,6 @@ class UserPreferences extends PersistedChangeNotifier {
|
|||||||
bool showSystemTrayIcon;
|
bool showSystemTrayIcon;
|
||||||
|
|
||||||
UserPreferences({
|
UserPreferences({
|
||||||
required this.geniusAccessToken,
|
|
||||||
required this.recommendationMarket,
|
required this.recommendationMarket,
|
||||||
required this.themeMode,
|
required this.themeMode,
|
||||||
required this.layoutMode,
|
required this.layoutMode,
|
||||||
@ -95,12 +92,6 @@ class UserPreferences extends PersistedChangeNotifier {
|
|||||||
updatePersistence();
|
updatePersistence();
|
||||||
}
|
}
|
||||||
|
|
||||||
void setGeniusAccessToken(String token) {
|
|
||||||
geniusAccessToken = token;
|
|
||||||
notifyListeners();
|
|
||||||
updatePersistence();
|
|
||||||
}
|
|
||||||
|
|
||||||
void setAccentColorScheme(SpotubeColor color) {
|
void setAccentColorScheme(SpotubeColor color) {
|
||||||
accentColorScheme = color;
|
accentColorScheme = color;
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
@ -172,8 +163,6 @@ class UserPreferences extends PersistedChangeNotifier {
|
|||||||
saveTrackLyrics = map["saveTrackLyrics"] ?? false;
|
saveTrackLyrics = map["saveTrackLyrics"] ?? false;
|
||||||
recommendationMarket = map["recommendationMarket"] ?? recommendationMarket;
|
recommendationMarket = map["recommendationMarket"] ?? recommendationMarket;
|
||||||
checkUpdate = map["checkUpdate"] ?? checkUpdate;
|
checkUpdate = map["checkUpdate"] ?? checkUpdate;
|
||||||
geniusAccessToken = map["geniusAccessToken"] ??
|
|
||||||
PrimitiveUtils.getRandomElement(lyricsSecrets);
|
|
||||||
|
|
||||||
themeMode = ThemeMode.values[map["themeMode"] ?? 0];
|
themeMode = ThemeMode.values[map["themeMode"] ?? 0];
|
||||||
accentColorScheme = map["accentColorScheme"] != null
|
accentColorScheme = map["accentColorScheme"] != null
|
||||||
@ -205,7 +194,6 @@ class UserPreferences extends PersistedChangeNotifier {
|
|||||||
return {
|
return {
|
||||||
"saveTrackLyrics": saveTrackLyrics,
|
"saveTrackLyrics": saveTrackLyrics,
|
||||||
"recommendationMarket": recommendationMarket,
|
"recommendationMarket": recommendationMarket,
|
||||||
"geniusAccessToken": geniusAccessToken,
|
|
||||||
"themeMode": themeMode.index,
|
"themeMode": themeMode.index,
|
||||||
"accentColorScheme": accentColorScheme.toString(),
|
"accentColorScheme": accentColorScheme.toString(),
|
||||||
"checkUpdate": checkUpdate,
|
"checkUpdate": checkUpdate,
|
||||||
@ -223,7 +211,6 @@ class UserPreferences extends PersistedChangeNotifier {
|
|||||||
final userPreferencesProvider = ChangeNotifierProvider(
|
final userPreferencesProvider = ChangeNotifierProvider(
|
||||||
(_) => UserPreferences(
|
(_) => UserPreferences(
|
||||||
accentColorScheme: SpotubeColor(Colors.blue.value, name: "Blue"),
|
accentColorScheme: SpotubeColor(Colors.blue.value, name: "Blue"),
|
||||||
geniusAccessToken: "",
|
|
||||||
recommendationMarket: 'US',
|
recommendationMarket: 'US',
|
||||||
themeMode: ThemeMode.system,
|
themeMode: ThemeMode.system,
|
||||||
layoutMode: kIsMobile ? LayoutMode.compact : LayoutMode.adaptive,
|
layoutMode: kIsMobile ? LayoutMode.compact : LayoutMode.adaptive,
|
||||||
|
@ -9,7 +9,7 @@ import 'package:spotube/models/logger.dart';
|
|||||||
import 'package:http/http.dart' as http;
|
import 'package:http/http.dart' as http;
|
||||||
import 'package:spotube/models/lyrics.dart';
|
import 'package:spotube/models/lyrics.dart';
|
||||||
import 'package:spotube/models/spotube_track.dart';
|
import 'package:spotube/models/spotube_track.dart';
|
||||||
import 'package:spotube/models/generated_secrets.dart';
|
|
||||||
import 'package:spotube/utils/primitive_utils.dart';
|
import 'package:spotube/utils/primitive_utils.dart';
|
||||||
import 'package:collection/collection.dart';
|
import 'package:collection/collection.dart';
|
||||||
import 'package:html/parser.dart' as parser;
|
import 'package:html/parser.dart' as parser;
|
||||||
@ -23,6 +23,7 @@ abstract class ServiceUtils {
|
|||||||
.trim();
|
.trim();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated("In favor spotify lyrics api, this isn't needed anymore")
|
||||||
static String getTitle(
|
static String getTitle(
|
||||||
String title, {
|
String title, {
|
||||||
List<String> artists = const [],
|
List<String> artists = const [],
|
||||||
@ -77,6 +78,7 @@ abstract class ServiceUtils {
|
|||||||
return lyrics;
|
return lyrics;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated("In favor spotify lyrics api, this isn't needed anymore")
|
||||||
static Future<List?> searchSong(
|
static Future<List?> searchSong(
|
||||||
String title,
|
String title,
|
||||||
List<String> artist, {
|
List<String> artist, {
|
||||||
@ -85,7 +87,7 @@ abstract class ServiceUtils {
|
|||||||
bool authHeader = false,
|
bool authHeader = false,
|
||||||
}) async {
|
}) async {
|
||||||
if (apiKey == "" || apiKey == null) {
|
if (apiKey == "" || apiKey == null) {
|
||||||
apiKey = PrimitiveUtils.getRandomElement(lyricsSecrets);
|
apiKey = PrimitiveUtils.getRandomElement(/* lyricsSecrets */ []);
|
||||||
}
|
}
|
||||||
const searchUrl = 'https://api.genius.com/search?q=';
|
const searchUrl = 'https://api.genius.com/search?q=';
|
||||||
String song =
|
String song =
|
||||||
@ -111,6 +113,7 @@ abstract class ServiceUtils {
|
|||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated("In favor spotify lyrics api, this isn't needed anymore")
|
||||||
static Future<String?> getLyrics(
|
static Future<String?> getLyrics(
|
||||||
String title,
|
String title,
|
||||||
List<String> artists, {
|
List<String> artists, {
|
||||||
@ -158,8 +161,10 @@ abstract class ServiceUtils {
|
|||||||
return lyrics;
|
return lyrics;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated("In favor spotify lyrics api, this isn't needed anymore")
|
||||||
static const baseUri = "https://www.rentanadviser.com/subtitles";
|
static const baseUri = "https://www.rentanadviser.com/subtitles";
|
||||||
|
|
||||||
|
@Deprecated("In favor spotify lyrics api, this isn't needed anymore")
|
||||||
static Future<SubtitleSimple?> getTimedLyrics(SpotubeTrack track) async {
|
static Future<SubtitleSimple?> getTimedLyrics(SpotubeTrack track) async {
|
||||||
final artistNames =
|
final artistNames =
|
||||||
track.artists?.map((artist) => artist.name!).toList() ?? [];
|
track.artists?.map((artist) => artist.name!).toList() ?? [];
|
||||||
|
@ -15,7 +15,6 @@ dependencies:
|
|||||||
- libappindicator3-1
|
- libappindicator3-1
|
||||||
- gir1.2-appindicator3-0.1
|
- gir1.2-appindicator3-0.1
|
||||||
- libsecret-1-0
|
- libsecret-1-0
|
||||||
- libjsoncpp1
|
|
||||||
|
|
||||||
essential: false
|
essential: false
|
||||||
icon: assets/spotube-logo.png
|
icon: assets/spotube-logo.png
|
||||||
|
24
pubspec.lock
24
pubspec.lock
@ -506,6 +506,22 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.0"
|
version: "2.1.0"
|
||||||
|
envied:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: envied
|
||||||
|
sha256: d5d978fbd578b5c00123003609c39185e0b1ddf9d2ac460d710dd0eb2fc223d7
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.3.0"
|
||||||
|
envied_generator:
|
||||||
|
dependency: "direct dev"
|
||||||
|
description:
|
||||||
|
name: envied_generator
|
||||||
|
sha256: "6c5a98c27c5eae925807692eb252ccac2b8e81f09bace1f07207c47dfb6a4eb0"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.3.0"
|
||||||
fake_async:
|
fake_async:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -624,14 +640,6 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.0.2"
|
version: "0.0.2"
|
||||||
flutter_dotenv:
|
|
||||||
dependency: "direct main"
|
|
||||||
description:
|
|
||||||
name: flutter_dotenv
|
|
||||||
sha256: d9283d92059a22e9834bc0a31336658ffba77089fb6f3cc36751f1fc7c6661a3
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "5.0.2"
|
|
||||||
flutter_driver:
|
flutter_driver:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description: flutter
|
description: flutter
|
||||||
|
@ -25,6 +25,7 @@ dependencies:
|
|||||||
cupertino_icons: ^1.0.5
|
cupertino_icons: ^1.0.5
|
||||||
curved_navigation_bar: ^1.0.3
|
curved_navigation_bar: ^1.0.3
|
||||||
dbus: ^0.7.8
|
dbus: ^0.7.8
|
||||||
|
envied: ^0.3.0
|
||||||
file_picker: ^5.2.2
|
file_picker: ^5.2.2
|
||||||
fl_query: ^1.0.0-alpha.2
|
fl_query: ^1.0.0-alpha.2
|
||||||
fl_query_hooks: ^1.0.0-alpha.2
|
fl_query_hooks: ^1.0.0-alpha.2
|
||||||
@ -32,7 +33,6 @@ dependencies:
|
|||||||
flutter:
|
flutter:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
flutter_cache_manager: ^3.3.0
|
flutter_cache_manager: ^3.3.0
|
||||||
flutter_dotenv: ^5.0.2
|
|
||||||
flutter_feather_icons: ^2.0.0+1
|
flutter_feather_icons: ^2.0.0+1
|
||||||
flutter_hooks: ^0.18.2+1
|
flutter_hooks: ^0.18.2+1
|
||||||
flutter_inappwebview: ^5.7.2+3
|
flutter_inappwebview: ^5.7.2+3
|
||||||
@ -92,6 +92,7 @@ dependencies:
|
|||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
build_runner: ^2.3.2
|
build_runner: ^2.3.2
|
||||||
|
envied_generator: ^0.3.0
|
||||||
flutter_distributor: ^0.0.2
|
flutter_distributor: ^0.0.2
|
||||||
flutter_gen_runner: ^5.1.0+1
|
flutter_gen_runner: ^5.1.0+1
|
||||||
flutter_launcher_icons: ^0.11.0
|
flutter_launcher_icons: ^0.11.0
|
||||||
@ -112,7 +113,6 @@ flutter:
|
|||||||
assets:
|
assets:
|
||||||
- assets/
|
- assets/
|
||||||
- assets/tutorial/
|
- assets/tutorial/
|
||||||
- .env
|
|
||||||
- LICENSE
|
- LICENSE
|
||||||
|
|
||||||
flutter_icons:
|
flutter_icons:
|
||||||
@ -130,5 +130,3 @@ flutter_icons:
|
|||||||
|
|
||||||
flutter_gen:
|
flutter_gen:
|
||||||
output: lib/collections
|
output: lib/collections
|
||||||
integrations:
|
|
||||||
flutter_svg: true
|
|
||||||
|
Loading…
Reference in New Issue
Block a user