Merge branch 'master' into build

Adds the latest modifications and features for build environment
This commit is contained in:
Kingkor Roy Tirtho 2022-03-18 12:20:58 +06:00
commit 50944cf466
26 changed files with 169 additions and 16 deletions

View File

@ -16,6 +16,7 @@ jobs:
- run: |
sudo apt-get update -y
sudo apt-get install -y tar clang cmake ninja-build pkg-config libgtk-3-dev make libwebkit2gtk-4.0-dev keybinder-3.0 python3-pip python3-setuptools patchelf desktop-file-utils libgdk-pixbuf2.0-dev fakeroot strace fuse
- run: dart bin/create-secrets.dart
- run: flutter config --enable-linux-desktop
- run: flutter pub get
- run: flutter clean
@ -26,6 +27,8 @@ jobs:
- run: chmod +x /usr/local/bin/appimagetool
- run: pip3 install appimage-builder
- run: make appimage
# Building Android Application
- run: flutter build apk
- uses: actions/upload-artifact@v2
with:
name: Spotube-Linux-Bundle
@ -33,6 +36,7 @@ jobs:
build/Spotube-linux-x86_64.deb
build/Spotube-linux-x86_64.tar.xz
build/Spotube-*-x86_64.AppImage
build/app/outputs/apk/release/app-release.apk
build_windows:
runs-on: windows-latest
steps:
@ -40,6 +44,7 @@ jobs:
- uses: subosito/flutter-action@v2.2.0
with:
cache: true
- run: dart bin/create-secrets.dart
- run: flutter config --enable-windows-desktop
- run: flutter build windows
- run: choco install make -y
@ -59,6 +64,7 @@ jobs:
- uses: subosito/flutter-action@v2
with:
cache: true
- run: dart bin/create-secrets.dart
- run: flutter config --enable-macos-desktop
- run: flutter build macos
- run: du -sh build/macos/Build/Products/Release/spotube.app

View File

@ -121,9 +121,15 @@ You need a spotify account & a developer app for
- Click on **SHOW CLIENT SECRET** to reveal the **clientSecret**. Then copy the **clientID**, **clientSecret** & paste in the **Spotube's** respective fields
![step-4](https://user-images.githubusercontent.com/61944859/111769501-7fe31e80-88d3-11eb-8fc1-f3655dbd4711.png)
Also, you need a [genius](https://genius.com) account for **lyrics** & a API Client for
**Setup Genius Lyrics (Optional)**
- accessToken
- Signup/Login into [genius](https://genius.com/signup) for **lyrics**
- Go To [Genius Developer Portal](https://genius.com/api-clients/new) for creating an API client
![Step 2](https://user-images.githubusercontent.com/61944859/158823216-b4942731-c4c5-46c8-8b60-82a372b51cc5.png)
- Generate & copy access token
![Step 3](https://user-images.githubusercontent.com/61944859/158822817-f04da060-3094-4a3b-8ace-a936d0cda8db.png)
- Paste the copied access token in Spotube's Settings
![Step 4](https://user-images.githubusercontent.com/61944859/158823984-17f08534-5c92-41bc-918a-23194aad00f5.png)
> **Note!**: No personal data or any kind of sensitive information won't be collected from spotify. Don't believe? See the code for yourself

View File

@ -48,6 +48,7 @@ android {
targetSdkVersion flutter.targetSdkVersion
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
multiDexEnabled true
}
buildTypes {
@ -65,4 +66,5 @@ flutter {
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'com.android.support:multidex:1.0.3'
}

View File

@ -1,6 +1,8 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="oss.krtirtho.spotube">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<queries>
<!-- If your app opens https URLs -->
@ -10,8 +12,8 @@
</intent>
</queries>
<application android:label="spotube" android:name="${applicationName}" android:icon="@mipmap/ic_launcher" android:usesCleartextTraffic="true">
<activity android:name=".MainActivity" android:exported="true" android:launchMode="singleTop" android:theme="@style/LaunchTheme" android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode" android:hardwareAccelerated="true" android:windowSoftInputMode="adjustResize">
<application android:label="Spotube" android:name="${applicationName}" android:icon="@mipmap/ic_launcher" android:usesCleartextTraffic="true">
<activity android:name="com.ryanheise.audioservice.AudioServiceActivity" android:exported="true" android:launchMode="singleTop" android:theme="@style/LaunchTheme" android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode" android:hardwareAccelerated="true" android:windowSoftInputMode="adjustResize">
<!-- Specifies an Android theme to apply to this Activity as soon as
the Android process has started. This theme is visible to the user
while the Flutter UI initializes. After that, this theme continues
@ -23,6 +25,19 @@
</intent-filter>
</activity>
<service android:name="com.ryanheise.audioservice.AudioService">
<intent-filter>
<action android:name="android.media.browse.MediaBrowserService" />
</intent-filter>
</service>
<receiver android:name="com.ryanheise.audioservice.MediaButtonReceiver">
<intent-filter>
<action android:name="android.intent.action.MEDIA_BUTTON" />
</intent-filter>
</receiver>
<!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
<meta-data android:name="flutterEmbedding" android:value="2" />

View File

@ -0,0 +1,20 @@
// Generated file.
// If you wish to remove Flutter's multidex support, delete this entire file.
package io.flutter.app;
import android.content.Context;
import androidx.annotation.CallSuper;
import androidx.multidex.MultiDex;
/**
* Extension of {@link io.flutter.app.FlutterApplication}, adding multidex support.
*/
public class FlutterMultiDexApplication extends FlutterApplication {
@Override
@CallSuper
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
MultiDex.install(this);
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_launcher_background"/>
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
</adaptive-icon>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 544 B

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 442 B

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 721 B

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 28 KiB

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="ic_launcher_background">#ffffff</color>
</resources>

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 KiB

19
bin/create-secrets.dart Normal file
View File

@ -0,0 +1,19 @@
import 'dart:convert';
import 'dart:io';
import 'package:path/path.dart' as path;
import 'package:dotenv/dotenv.dart';
void main() async {
load();
final bool hasKey = env.containsKey("SECRET");
final val = hasKey ? jsonDecode(env["SECRET"]!) : null;
if (!hasKey || (hasKey && val is! List)) {
throw Exception(
"'SECRET' Environmental Variable isn't configured properly");
}
await File(path.join(
Directory.current.path, "lib/models/generated_secrets.dart"))
.writeAsString("final List<String> secrets = ${env["SECRET"]};");
}

View File

@ -3,8 +3,6 @@ import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:go_router/go_router.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:spotify/spotify.dart';
import 'package:spotube/components/Settings.dart';
import 'package:spotube/components/Shared/SpotubePageRoute.dart';
import 'package:spotube/helpers/artist-to-string.dart';
import 'package:spotube/helpers/getLyrics.dart';
import 'package:spotube/provider/Playback.dart';
@ -39,7 +37,9 @@ class Lyrics extends HookConsumerWidget {
var lyricsSnapshot = useFuture(lyricsFuture);
useEffect(() {
if (lyricsSnapshot.hasData && lyricsSnapshot.data != null) {
if (lyricsSnapshot.hasData &&
lyricsSnapshot.data != null &&
playback.currentTrack != null) {
lyrics.value = {
"lyrics": lyricsSnapshot.data,
"id": playback.currentTrack!.id!

View File

@ -0,0 +1,6 @@
import 'dart:math';
final Random _random = Random();
T getRandomElement<T>(List<T> list) {
return list[_random.nextInt(list.length)];
}

View File

@ -2,6 +2,8 @@ import 'dart:convert';
import 'package:html/parser.dart' as parser;
import 'package:html/dom.dart';
import 'package:http/http.dart' as http;
import 'package:spotube/helpers/get-random-element.dart';
import 'package:spotube/models/generated_secrets.dart';
String getTitle(String title, String artist) {
return "$title $artist"
@ -47,16 +49,17 @@ Future<String?> extractLyrics(Uri url) async {
Future<List?> searchSong(
String title,
String artist, {
String apiKey = "",
String? apiKey,
bool optimizeQuery = false,
bool authHeader = false,
}) async {
try {
if (apiKey == "" || apiKey == null) apiKey = getRandomElement(secrets);
const searchUrl = 'https://api.genius.com/search?q=';
String song = optimizeQuery ? getTitle(title, artist) : "$title $artist";
String reqUrl = "$searchUrl${Uri.encodeComponent(song)}";
Map<String, String> headers = {"Authorization": 'Bearer ' + apiKey};
Map<String, String> headers = {"Authorization": 'Bearer $apiKey'};
var response = await http.get(
Uri.parse(authHeader ? reqUrl : "$reqUrl&access_token=$apiKey"),
headers: authHeader ? headers : null,
@ -100,5 +103,6 @@ Future<String?> getLyrics(
} catch (e, stack) {
print("[getLyrics] $e");
print(stack);
return null;
}
}

View File

@ -12,9 +12,16 @@ import 'package:spotube/models/LocalStorageKeys.dart';
import 'package:spotube/provider/AudioPlayer.dart';
import 'package:spotube/provider/ThemeProvider.dart';
import 'package:spotube/provider/YouTube.dart';
import 'package:just_audio_background/just_audio_background.dart';
void main() async {
if (!Platform.isAndroid && !Platform.isIOS) {
if (Platform.isAndroid || Platform.isIOS) {
await JustAudioBackground.init(
androidNotificationChannelId: 'oss.krtirtho.Spotube',
androidNotificationChannelName: 'Spotube',
androidNotificationOngoing: true,
);
} else {
WidgetsFlutterBinding.ensureInitialized();
await hotKeyManager.unregisterAll();
doWhenWindowReady(() {

View File

@ -4,7 +4,10 @@ import 'package:audio_session/audio_session.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:just_audio/just_audio.dart';
import 'package:just_audio_background/just_audio_background.dart';
import 'package:spotify/spotify.dart';
import 'package:spotube/helpers/artist-to-string.dart';
import 'package:spotube/helpers/image-to-url-string.dart';
import 'package:spotube/helpers/search-youtube.dart';
import 'package:spotube/provider/AudioPlayer.dart';
import 'package:spotube/provider/YouTube.dart';
@ -221,10 +224,17 @@ class Playback extends ChangeNotifier {
track ??= _currentTrack;
if (track != null && await _audioSession?.setActive(true) == true) {
Uri? parsedUri = Uri.tryParse(track.uri ?? "");
final tag = MediaItem(
id: track.id!,
title: track.name!,
album: track.album?.name,
artist: artistsToString(track.artists ?? <ArtistSimple>[]),
artUri: Uri.parse(imageToUrlString(track.album?.images)),
);
if (parsedUri != null && parsedUri.hasAbsolutePath) {
await player
.setAudioSource(
AudioSource.uri(parsedUri),
AudioSource.uri(parsedUri, tag: tag),
preload: true,
)
.then((value) async {
@ -238,7 +248,7 @@ class Playback extends ChangeNotifier {
if (setTrackUriById(track.id!, ytTrack.uri!)) {
await player
.setAudioSource(
AudioSource.uri(Uri.parse(ytTrack.uri!)),
AudioSource.uri(Uri.parse(ytTrack.uri!), tag: tag),
preload: true,
)
.then((value) {

View File

@ -29,6 +29,27 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "2.8.2"
audio_service:
dependency: transitive
description:
name: audio_service
url: "https://pub.dartlang.org"
source: hosted
version: "0.18.4"
audio_service_platform_interface:
dependency: transitive
description:
name: audio_service_platform_interface
url: "https://pub.dartlang.org"
source: hosted
version: "0.1.0"
audio_service_web:
dependency: transitive
description:
name: audio_service_web
url: "https://pub.dartlang.org"
source: hosted
version: "0.1.1"
audio_session:
dependency: "direct main"
description:
@ -148,6 +169,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.4"
dotenv:
dependency: "direct dev"
description:
name: dotenv
url: "https://pub.dartlang.org"
source: hosted
version: "3.0.0"
fake_async:
dependency: transitive
description:
@ -195,6 +223,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "0.18.2+1"
flutter_launcher_icons:
dependency: "direct dev"
description:
name: flutter_launcher_icons
url: "https://pub.dartlang.org"
source: hosted
version: "0.9.2"
flutter_lints:
dependency: "direct dev"
description:
@ -303,6 +338,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "0.9.20"
just_audio_background:
dependency: "direct main"
description:
name: just_audio_background
url: "https://pub.dartlang.org"
source: hosted
version: "0.0.1-beta.5"
just_audio_libwinmedia:
dependency: "direct main"
description:

View File

@ -3,7 +3,7 @@ description: A lightweight free Spotify desktop-client which handles playback ma
# The following line prevents the package from being accidentally published to
# pub.dev using `flutter pub publish`. This is preferred for private packages.
publish_to: 'none' # Remove this line if you wish to publish to pub.dev
publish_to: "none" # Remove this line if you wish to publish to pub.dev
# The following defines the version and build number for your application.
# A version number is three numbers separated by dots, like 1.2.43
@ -30,7 +30,6 @@ dependencies:
flutter:
sdk: flutter
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^1.0.2
@ -55,6 +54,7 @@ dependencies:
go_router: ^3.0.4
palette_generator: ^0.3.3
audio_session: ^0.1.6+1
just_audio_background: ^0.0.1-beta.5
dev_dependencies:
flutter_test:
@ -67,13 +67,14 @@ dev_dependencies:
# package. See that file for information about deactivating specific lint
# rules and activating additional ones.
flutter_lints: ^1.0.0
flutter_launcher_icons: ^0.9.2
dotenv: ^3.0.0
# For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec
# The following section is specific to Flutter.
flutter:
# The following line ensures that the Material Icons font is
# included with your application, so that you can use the icons in
# the material Icons class.
@ -116,4 +117,10 @@ msix_config:
identity_name: oss.krtirtho.spotube
msix_version: 1.0.1.0
logo_path: .\assets\spotube-logo.png
capabilities: "internetClient,internetClientServer,backgroundMediaPlayback"
capabilities: "internetClient,internetClientServer,backgroundMediaPlayback"
flutter_icons:
android: true
image_path: "assets/spotube-logo.png"
adaptive_icon_foreground: "assets/spotube-logo-foreground.png"
adaptive_icon_background: "#ffffff"