mirror of
https://github.com/KRTirtho/spotube.git
synced 2025-09-13 07:55:18 +00:00
Compare commits
10 Commits
1b70937603
...
abdb2dcc3f
Author | SHA1 | Date | |
---|---|---|---|
![]() |
abdb2dcc3f | ||
![]() |
90493f0ea3 | ||
![]() |
db22b4fcce | ||
![]() |
0d6d482630 | ||
![]() |
a4162dc2ad | ||
![]() |
469a76dbd6 | ||
![]() |
6940e92142 | ||
![]() |
ff252d6b14 | ||
![]() |
195cad8f39 | ||
![]() |
19f525fa3c |
3
Makefile
3
Makefile
@ -53,3 +53,6 @@ dmg:
|
||||
then rm dist/Spotube-macos-universal.dmg;\
|
||||
fi &&\
|
||||
appdmg appdmg.json dist/Spotube-macos-universal.dmg
|
||||
|
||||
changelog:
|
||||
git-cliff --unreleased
|
92
cliff.toml
Normal file
92
cliff.toml
Normal file
@ -0,0 +1,92 @@
|
||||
# git-cliff ~ configuration file
|
||||
# https://git-cliff.org/docs/configuration
|
||||
|
||||
|
||||
[changelog]
|
||||
# A Tera template to be rendered for each release in the changelog.
|
||||
# See https://keats.github.io/tera/docs/#introduction
|
||||
body = """
|
||||
{% if version %}\
|
||||
## [{{ version | trim_start_matches(pat="v") }}](<REPO>/compare/v{{ previous.version | trim_start_matches(pat="v") }}...v{{ version | trim_start_matches(pat="v") }}) ({{ timestamp | date(format="%Y-%m-%d") }})
|
||||
{% else %}\
|
||||
## [unreleased]
|
||||
{% endif %}\
|
||||
{% for group, commits in commits | group_by(attribute="group") %}
|
||||
### {{ group | striptags | trim | upper_first }}
|
||||
{% for commit in commits %}
|
||||
- {% if commit.scope %}**{{ commit.scope }}**: {% endif %}\
|
||||
{% if commit.breaking %}[**breaking**] {% endif %}\
|
||||
{{ commit.message | upper_first }}\
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
"""
|
||||
# Remove leading and trailing whitespaces from the changelog's body.
|
||||
trim = true
|
||||
# Render body even when there are no releases to process.
|
||||
render_always = true
|
||||
# An array of regex based postprocessors to modify the changelog.
|
||||
postprocessors = [
|
||||
# Replace the placeholder <REPO> with a URL.
|
||||
{ pattern = '<REPO>', replace = "https://github.com/KRTirtho/spotube" },
|
||||
]
|
||||
# render body even when there are no releases to process
|
||||
# render_always = true
|
||||
# output file path
|
||||
# output = "test.md"
|
||||
|
||||
[git]
|
||||
# Parse commits according to the conventional commits specification.
|
||||
# See https://www.conventionalcommits.org
|
||||
conventional_commits = true
|
||||
# Exclude commits that do not match the conventional commits specification.
|
||||
filter_unconventional = true
|
||||
# Require all commits to be conventional.
|
||||
# Takes precedence over filter_unconventional.
|
||||
require_conventional = false
|
||||
# Split commits on newlines, treating each line as an individual commit.
|
||||
split_commits = false
|
||||
# An array of regex based parsers to modify commit messages prior to further processing.
|
||||
commit_preprocessors = [
|
||||
# Replace issue numbers with link templates to be updated in `changelog.postprocessors`.
|
||||
{ pattern = '\((\w+\s)?#([0-9]+)\)', replace = "([#${2}](<REPO>/issues/${2}))" },
|
||||
# Check spelling of the commit message using https://github.com/crate-ci/typos.
|
||||
# If the spelling is incorrect, it will be fixed automatically.
|
||||
#{ pattern = '.*', replace_command = 'typos --write-changes -' },
|
||||
]
|
||||
# Prevent commits that are breaking from being excluded by commit parsers.
|
||||
protect_breaking_commits = false
|
||||
# An array of regex based parsers for extracting data from the commit message.
|
||||
# Assigns commits to groups.
|
||||
# Optionally sets the commit's scope and can decide to exclude commits from further processing.
|
||||
commit_parsers = [
|
||||
{ message = "^feat", group = "<!-- 0 -->Features" },
|
||||
{ message = "^fix", group = "<!-- 1 -->Bug Fixes" },
|
||||
# { message = "^doc", group = "<!-- 3 -->📚 Documentation" },
|
||||
# { message = "^perf", group = "<!-- 4 -->⚡ Performance" },
|
||||
# { message = "^refactor", group = "<!-- 2 -->🚜 Refactor" },
|
||||
# { message = "^style", group = "<!-- 5 -->🎨 Styling" },
|
||||
# { message = "^test", group = "<!-- 6 -->🧪 Testing" },
|
||||
# { message = "^chore\\(release\\): prepare for", skip = true },
|
||||
# { message = "^chore\\(deps.*\\)", skip = true },
|
||||
# { message = "^chore\\(pr\\)", skip = true },
|
||||
# { message = "^chore\\(pull\\)", skip = true },
|
||||
# { message = "^chore|^ci", group = "<!-- 7 -->⚙️ Miscellaneous Tasks" },
|
||||
# { body = ".*security", group = "<!-- 8 -->🛡️ Security" },
|
||||
# { message = "^revert", group = "<!-- 9 -->◀️ Revert" },
|
||||
# { message = ".*", group = "<!-- 10 -->💼 Other" },
|
||||
]
|
||||
# Exclude commits that are not matched by any commit parser.
|
||||
filter_commits = true
|
||||
# An array of link parsers for extracting external references, and turning them into URLs, using regex.
|
||||
link_parsers = []
|
||||
# Include only the tags that belong to the current branch.
|
||||
use_branch_tags = false
|
||||
# Order releases topologically instead of chronologically.
|
||||
topo_order = false
|
||||
# Order releases topologically instead of chronologically.
|
||||
topo_order_commits = true
|
||||
# Order of commits in each group/release within the changelog.
|
||||
# Allowed values: newest, oldest
|
||||
sort_commits = "oldest"
|
||||
# Process submodules commits
|
||||
recurse_submodules = false
|
1
drift_schemas/app_db/drift_schema_v8.json
Normal file
1
drift_schemas/app_db/drift_schema_v8.json
Normal file
File diff suppressed because one or more lines are too long
@ -16,12 +16,16 @@ class $AssetsBrandingGen {
|
||||
AssetGenImage get spotubeLogoLight =>
|
||||
const AssetGenImage('assets/branding/spotube-logo-light.png');
|
||||
|
||||
/// File path: assets/branding/spotube-logo.ico
|
||||
String get spotubeLogoIco => 'assets/branding/spotube-logo.ico';
|
||||
|
||||
/// File path: assets/branding/spotube-logo.png
|
||||
AssetGenImage get spotubeLogo =>
|
||||
AssetGenImage get spotubeLogoPng =>
|
||||
const AssetGenImage('assets/branding/spotube-logo.png');
|
||||
|
||||
/// List of all assets
|
||||
List<AssetGenImage> get values => [spotubeLogoLight, spotubeLogo];
|
||||
List<dynamic> get values =>
|
||||
[spotubeLogoLight, spotubeLogoIco, spotubeLogoPng];
|
||||
}
|
||||
|
||||
class $AssetsImagesGen {
|
||||
|
@ -137,16 +137,16 @@
|
||||
"pre_download_play_description": "Anzi che effettuare lo stream dell'audio, scarica invece i byte e li riproduce (raccomandato per gli utenti con banda più alta)",
|
||||
"skip_non_music": "Salta i segmenti non di musica (SponsorBlock)",
|
||||
"blacklist_description": "Tracce e artisti in blacklist",
|
||||
"wait_for_download_to_finish": "Prego attendere che lo scaricamento corrente finisca",
|
||||
"wait_for_download_to_finish": "Prego attendere che il download corrente finisca",
|
||||
"desktop": "Desktop",
|
||||
"close_behavior": "Comportamento Chiusura",
|
||||
"close": "Chiudi",
|
||||
"minimize_to_tray": "Minimizza in tray",
|
||||
"show_tray_icon": "Mostra icona in tray di sistema",
|
||||
"about": "A proposito di",
|
||||
"about": "Informazioni su",
|
||||
"u_love_spotube": "Sappiamo che ami Spotube",
|
||||
"check_for_updates": "Controlla aggiornamenti",
|
||||
"about_spotube": "A proposito di Spotube",
|
||||
"about_spotube": "Informazioni su Spotube",
|
||||
"blacklist": "Blacklist",
|
||||
"please_sponsor": "Per favore sponsorizza/dona",
|
||||
"spotube_description": "Spotube, un client spotify gratis per tutti, multipiattaforma e leggero",
|
||||
@ -187,7 +187,7 @@
|
||||
"generate_playlist": "Genera Playlist",
|
||||
"track_exists": "La traccia {track} esiste già",
|
||||
"replace_downloaded_tracks": "Sostituisci tutte le tracce scaricate",
|
||||
"skip_download_tracks": "Salta lo scaricamento di tutte le tracce scaricate",
|
||||
"skip_download_tracks": "Salta il download di tutte le tracce scaricate",
|
||||
"do_you_want_to_replace": "Vuoi sovrascrivere la traccia esistente??",
|
||||
"replace": "Sovrascrivi",
|
||||
"skip": "Salta",
|
||||
@ -256,7 +256,7 @@
|
||||
"querying_info": "Richiesta informazioni...",
|
||||
"piped_api_down": "Le Piped API non funzionano",
|
||||
"piped_down_error_instructions": "L'istanza di Piped {pipedInstance} è correntemente offline\n\nCambia istanza o cambia 'Tipo API' alle API ufficiali YouTube\n\nAssicurati di riavviare l'app dopo il cambio",
|
||||
"you_are_offline": "Sei correntemente offline",
|
||||
"you_are_offline": "Al momento sei offline",
|
||||
"connection_restored": "Connessione ad internet ripristinata",
|
||||
"use_system_title_bar": "Usa la barra del titolo di sistema",
|
||||
"crunching_results": "Elaborazione risultati...",
|
||||
@ -267,15 +267,15 @@
|
||||
"change_cover": "Cambia copertina",
|
||||
"add_cover": "Aggiungi copertina",
|
||||
"restore_defaults": "Ripristina default",
|
||||
"download_music_codec": "Codec musicale scaricamento",
|
||||
"streaming_music_codec": "Codec musicale streaming",
|
||||
"login_with_lastfm": "Accesso a Last.fm",
|
||||
"connect": "Connetti",
|
||||
"disconnect_lastfm": "Disconnetti Last.fm",
|
||||
"download_music_codec": "Codec download musica",
|
||||
"streaming_music_codec": "Codec streaming musica",
|
||||
"login_with_lastfm": "Accedi con Last.fm",
|
||||
"connect": "Connettiti",
|
||||
"disconnect_lastfm": "Disconnettiti da Last.fm",
|
||||
"disconnect": "Disconnetti",
|
||||
"username": "Nome utente",
|
||||
"password": "Password",
|
||||
"login": "Accesso",
|
||||
"login": "Accedi",
|
||||
"login_with_your_lastfm": "Accedi con il tuo account Last.fm",
|
||||
"scrobble_to_lastfm": "Invia a Last.fm",
|
||||
"audio_source": "Fonte audio",
|
||||
@ -299,7 +299,7 @@
|
||||
"song_link": "Link della Canzone",
|
||||
"skip_this_nonsense": "Salta questa sciocchezza",
|
||||
"freedom_of_music": "“Libertà della Musica”",
|
||||
"freedom_of_music_palm": "“Libertà della Musica nel palmo della tua mano”",
|
||||
"freedom_of_music_palm": "“Libertà della Musica nelle tue mani”",
|
||||
"get_started": "Cominciamo",
|
||||
"youtube_source_description": "Consigliato e funziona meglio.",
|
||||
"piped_source_description": "Ti senti libero? Come YouTube ma molto più gratuito.",
|
||||
|
@ -65,7 +65,7 @@ class AppDatabase extends _$AppDatabase {
|
||||
AppDatabase() : super(_openConnection());
|
||||
|
||||
@override
|
||||
int get schemaVersion => 7;
|
||||
int get schemaVersion => 8;
|
||||
|
||||
@override
|
||||
MigrationStrategy get migration {
|
||||
@ -142,6 +142,63 @@ class AppDatabase extends _$AppDatabase {
|
||||
schema.audioPlayerStateTable.tracks,
|
||||
);
|
||||
},
|
||||
from7To8: (m, schema) async {
|
||||
await m
|
||||
.addColumn(
|
||||
schema.metadataPluginsTable,
|
||||
schema.metadataPluginsTable.entryPoint,
|
||||
)
|
||||
.catchError((error, stackTrace) {
|
||||
// If the column already exists, ignore the error
|
||||
if (!error.toString().contains('duplicate column name')) {
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
await m
|
||||
.addColumn(
|
||||
schema.metadataPluginsTable,
|
||||
schema.metadataPluginsTable.apis,
|
||||
)
|
||||
.catchError((error, stackTrace) {
|
||||
// If the column already exists, ignore the error
|
||||
if (!error.toString().contains('duplicate column name')) {
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
await m
|
||||
.addColumn(
|
||||
schema.metadataPluginsTable,
|
||||
schema.metadataPluginsTable.abilities,
|
||||
)
|
||||
.catchError((error, stackTrace) {
|
||||
// If the column already exists, ignore the error
|
||||
if (!error.toString().contains('duplicate column name')) {
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
await m
|
||||
.addColumn(
|
||||
schema.metadataPluginsTable,
|
||||
schema.metadataPluginsTable.repository,
|
||||
)
|
||||
.catchError((error, stackTrace) {
|
||||
// If the column already exists, ignore the error
|
||||
if (!error.toString().contains('duplicate column name')) {
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
await m
|
||||
.addColumn(
|
||||
schema.metadataPluginsTable,
|
||||
schema.metadataPluginsTable.pluginApiVersion,
|
||||
)
|
||||
.catchError((error, stackTrace) {
|
||||
// If the column already exists, ignore the error
|
||||
if (!error.toString().contains('duplicate column name')) {
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
@ -3889,7 +3889,9 @@ class $MetadataPluginsTableTable extends MetadataPluginsTable
|
||||
@override
|
||||
late final GeneratedColumn<String> pluginApiVersion = GeneratedColumn<String>(
|
||||
'plugin_api_version', aliasedName, false,
|
||||
type: DriftSqlType.string, requiredDuringInsert: true);
|
||||
type: DriftSqlType.string,
|
||||
requiredDuringInsert: false,
|
||||
defaultValue: const Constant('1.0.0'));
|
||||
@override
|
||||
List<GeneratedColumn> get $columns => [
|
||||
id,
|
||||
@ -3969,8 +3971,6 @@ class $MetadataPluginsTableTable extends MetadataPluginsTable
|
||||
_pluginApiVersionMeta,
|
||||
pluginApiVersion.isAcceptableOrUnknown(
|
||||
data['plugin_api_version']!, _pluginApiVersionMeta));
|
||||
} else if (isInserting) {
|
||||
context.missing(_pluginApiVersionMeta);
|
||||
}
|
||||
return context;
|
||||
}
|
||||
@ -4245,15 +4245,14 @@ class MetadataPluginsTableCompanion
|
||||
required List<String> abilities,
|
||||
this.selected = const Value.absent(),
|
||||
this.repository = const Value.absent(),
|
||||
required String pluginApiVersion,
|
||||
this.pluginApiVersion = const Value.absent(),
|
||||
}) : name = Value(name),
|
||||
description = Value(description),
|
||||
version = Value(version),
|
||||
author = Value(author),
|
||||
entryPoint = Value(entryPoint),
|
||||
apis = Value(apis),
|
||||
abilities = Value(abilities),
|
||||
pluginApiVersion = Value(pluginApiVersion);
|
||||
abilities = Value(abilities);
|
||||
static Insertable<MetadataPluginsTableData> custom({
|
||||
Expression<int>? id,
|
||||
Expression<String>? name,
|
||||
@ -6365,7 +6364,7 @@ typedef $$MetadataPluginsTableTableCreateCompanionBuilder
|
||||
required List<String> abilities,
|
||||
Value<bool> selected,
|
||||
Value<String?> repository,
|
||||
required String pluginApiVersion,
|
||||
Value<String> pluginApiVersion,
|
||||
});
|
||||
typedef $$MetadataPluginsTableTableUpdateCompanionBuilder
|
||||
= MetadataPluginsTableCompanion Function({
|
||||
@ -6583,7 +6582,7 @@ class $$MetadataPluginsTableTableTableManager extends RootTableManager<
|
||||
required List<String> abilities,
|
||||
Value<bool> selected = const Value.absent(),
|
||||
Value<String?> repository = const Value.absent(),
|
||||
required String pluginApiVersion,
|
||||
Value<String> pluginApiVersion = const Value.absent(),
|
||||
}) =>
|
||||
MetadataPluginsTableCompanion.insert(
|
||||
id: id,
|
||||
|
@ -1,4 +1,3 @@
|
||||
// dart format width=80
|
||||
import 'package:drift/internal/versioned_schema.dart' as i0;
|
||||
import 'package:drift/drift.dart' as i1;
|
||||
import 'package:drift/drift.dart'; // ignore_for_file: type=lint,unused_import
|
||||
@ -1989,6 +1988,220 @@ i1.GeneratedColumn<String> _column_67(String aliasedName) =>
|
||||
i1.GeneratedColumn<String> _column_68(String aliasedName) =>
|
||||
i1.GeneratedColumn<String>('plugin_api_version', aliasedName, false,
|
||||
type: i1.DriftSqlType.string);
|
||||
|
||||
final class Schema8 extends i0.VersionedSchema {
|
||||
Schema8({required super.database}) : super(version: 8);
|
||||
@override
|
||||
late final List<i1.DatabaseSchemaEntity> entities = [
|
||||
authenticationTable,
|
||||
blacklistTable,
|
||||
preferencesTable,
|
||||
scrobblerTable,
|
||||
skipSegmentTable,
|
||||
sourceMatchTable,
|
||||
audioPlayerStateTable,
|
||||
historyTable,
|
||||
lyricsTable,
|
||||
metadataPluginsTable,
|
||||
uniqueBlacklist,
|
||||
uniqTrackMatch,
|
||||
];
|
||||
late final Shape0 authenticationTable = Shape0(
|
||||
source: i0.VersionedTable(
|
||||
entityName: 'authentication_table',
|
||||
withoutRowId: false,
|
||||
isStrict: false,
|
||||
tableConstraints: [],
|
||||
columns: [
|
||||
_column_0,
|
||||
_column_1,
|
||||
_column_2,
|
||||
_column_3,
|
||||
],
|
||||
attachedDatabase: database,
|
||||
),
|
||||
alias: null);
|
||||
late final Shape1 blacklistTable = Shape1(
|
||||
source: i0.VersionedTable(
|
||||
entityName: 'blacklist_table',
|
||||
withoutRowId: false,
|
||||
isStrict: false,
|
||||
tableConstraints: [],
|
||||
columns: [
|
||||
_column_0,
|
||||
_column_4,
|
||||
_column_5,
|
||||
_column_6,
|
||||
],
|
||||
attachedDatabase: database,
|
||||
),
|
||||
alias: null);
|
||||
late final Shape13 preferencesTable = Shape13(
|
||||
source: i0.VersionedTable(
|
||||
entityName: 'preferences_table',
|
||||
withoutRowId: false,
|
||||
isStrict: false,
|
||||
tableConstraints: [],
|
||||
columns: [
|
||||
_column_0,
|
||||
_column_7,
|
||||
_column_8,
|
||||
_column_9,
|
||||
_column_10,
|
||||
_column_11,
|
||||
_column_12,
|
||||
_column_13,
|
||||
_column_14,
|
||||
_column_15,
|
||||
_column_55,
|
||||
_column_17,
|
||||
_column_18,
|
||||
_column_19,
|
||||
_column_20,
|
||||
_column_21,
|
||||
_column_22,
|
||||
_column_23,
|
||||
_column_24,
|
||||
_column_25,
|
||||
_column_26,
|
||||
_column_54,
|
||||
_column_27,
|
||||
_column_28,
|
||||
_column_29,
|
||||
_column_30,
|
||||
_column_31,
|
||||
_column_56,
|
||||
_column_53,
|
||||
],
|
||||
attachedDatabase: database,
|
||||
),
|
||||
alias: null);
|
||||
late final Shape3 scrobblerTable = Shape3(
|
||||
source: i0.VersionedTable(
|
||||
entityName: 'scrobbler_table',
|
||||
withoutRowId: false,
|
||||
isStrict: false,
|
||||
tableConstraints: [],
|
||||
columns: [
|
||||
_column_0,
|
||||
_column_32,
|
||||
_column_33,
|
||||
_column_34,
|
||||
],
|
||||
attachedDatabase: database,
|
||||
),
|
||||
alias: null);
|
||||
late final Shape4 skipSegmentTable = Shape4(
|
||||
source: i0.VersionedTable(
|
||||
entityName: 'skip_segment_table',
|
||||
withoutRowId: false,
|
||||
isStrict: false,
|
||||
tableConstraints: [],
|
||||
columns: [
|
||||
_column_0,
|
||||
_column_35,
|
||||
_column_36,
|
||||
_column_37,
|
||||
_column_32,
|
||||
],
|
||||
attachedDatabase: database,
|
||||
),
|
||||
alias: null);
|
||||
late final Shape5 sourceMatchTable = Shape5(
|
||||
source: i0.VersionedTable(
|
||||
entityName: 'source_match_table',
|
||||
withoutRowId: false,
|
||||
isStrict: false,
|
||||
tableConstraints: [],
|
||||
columns: [
|
||||
_column_0,
|
||||
_column_37,
|
||||
_column_38,
|
||||
_column_39,
|
||||
_column_32,
|
||||
],
|
||||
attachedDatabase: database,
|
||||
),
|
||||
alias: null);
|
||||
late final Shape14 audioPlayerStateTable = Shape14(
|
||||
source: i0.VersionedTable(
|
||||
entityName: 'audio_player_state_table',
|
||||
withoutRowId: false,
|
||||
isStrict: false,
|
||||
tableConstraints: [],
|
||||
columns: [
|
||||
_column_0,
|
||||
_column_40,
|
||||
_column_41,
|
||||
_column_42,
|
||||
_column_43,
|
||||
_column_57,
|
||||
_column_58,
|
||||
],
|
||||
attachedDatabase: database,
|
||||
),
|
||||
alias: null);
|
||||
late final Shape9 historyTable = Shape9(
|
||||
source: i0.VersionedTable(
|
||||
entityName: 'history_table',
|
||||
withoutRowId: false,
|
||||
isStrict: false,
|
||||
tableConstraints: [],
|
||||
columns: [
|
||||
_column_0,
|
||||
_column_32,
|
||||
_column_50,
|
||||
_column_51,
|
||||
_column_52,
|
||||
],
|
||||
attachedDatabase: database,
|
||||
),
|
||||
alias: null);
|
||||
late final Shape10 lyricsTable = Shape10(
|
||||
source: i0.VersionedTable(
|
||||
entityName: 'lyrics_table',
|
||||
withoutRowId: false,
|
||||
isStrict: false,
|
||||
tableConstraints: [],
|
||||
columns: [
|
||||
_column_0,
|
||||
_column_37,
|
||||
_column_52,
|
||||
],
|
||||
attachedDatabase: database,
|
||||
),
|
||||
alias: null);
|
||||
late final Shape15 metadataPluginsTable = Shape15(
|
||||
source: i0.VersionedTable(
|
||||
entityName: 'metadata_plugins_table',
|
||||
withoutRowId: false,
|
||||
isStrict: false,
|
||||
tableConstraints: [],
|
||||
columns: [
|
||||
_column_0,
|
||||
_column_59,
|
||||
_column_60,
|
||||
_column_61,
|
||||
_column_62,
|
||||
_column_63,
|
||||
_column_64,
|
||||
_column_65,
|
||||
_column_66,
|
||||
_column_67,
|
||||
_column_69,
|
||||
],
|
||||
attachedDatabase: database,
|
||||
),
|
||||
alias: null);
|
||||
final i1.Index uniqueBlacklist = i1.Index('unique_blacklist',
|
||||
'CREATE UNIQUE INDEX unique_blacklist ON blacklist_table (element_type, element_id)');
|
||||
final i1.Index uniqTrackMatch = i1.Index('uniq_track_match',
|
||||
'CREATE UNIQUE INDEX uniq_track_match ON source_match_table (track_id, source_id, source_type)');
|
||||
}
|
||||
|
||||
i1.GeneratedColumn<String> _column_69(String aliasedName) =>
|
||||
i1.GeneratedColumn<String>('plugin_api_version', aliasedName, false,
|
||||
type: i1.DriftSqlType.string, defaultValue: const Constant('1.0.0'));
|
||||
i0.MigrationStepWithVersion migrationSteps({
|
||||
required Future<void> Function(i1.Migrator m, Schema2 schema) from1To2,
|
||||
required Future<void> Function(i1.Migrator m, Schema3 schema) from2To3,
|
||||
@ -1996,6 +2209,7 @@ i0.MigrationStepWithVersion migrationSteps({
|
||||
required Future<void> Function(i1.Migrator m, Schema5 schema) from4To5,
|
||||
required Future<void> Function(i1.Migrator m, Schema6 schema) from5To6,
|
||||
required Future<void> Function(i1.Migrator m, Schema7 schema) from6To7,
|
||||
required Future<void> Function(i1.Migrator m, Schema8 schema) from7To8,
|
||||
}) {
|
||||
return (currentVersion, database) async {
|
||||
switch (currentVersion) {
|
||||
@ -2029,6 +2243,11 @@ i0.MigrationStepWithVersion migrationSteps({
|
||||
final migrator = i1.Migrator(database, schema);
|
||||
await from6To7(migrator, schema);
|
||||
return 7;
|
||||
case 7:
|
||||
final schema = Schema8(database: database);
|
||||
final migrator = i1.Migrator(database, schema);
|
||||
await from7To8(migrator, schema);
|
||||
return 8;
|
||||
default:
|
||||
throw ArgumentError.value('Unknown migration from $currentVersion');
|
||||
}
|
||||
@ -2042,6 +2261,7 @@ i1.OnUpgrade stepByStep({
|
||||
required Future<void> Function(i1.Migrator m, Schema5 schema) from4To5,
|
||||
required Future<void> Function(i1.Migrator m, Schema6 schema) from5To6,
|
||||
required Future<void> Function(i1.Migrator m, Schema7 schema) from6To7,
|
||||
required Future<void> Function(i1.Migrator m, Schema8 schema) from7To8,
|
||||
}) =>
|
||||
i0.VersionedSchema.stepByStepHelper(
|
||||
step: migrationSteps(
|
||||
@ -2051,4 +2271,5 @@ i1.OnUpgrade stepByStep({
|
||||
from4To5: from4To5,
|
||||
from5To6: from5To6,
|
||||
from6To7: from6To7,
|
||||
from7To8: from7To8,
|
||||
));
|
||||
|
@ -11,5 +11,6 @@ class MetadataPluginsTable extends Table {
|
||||
TextColumn get abilities => text().map(const StringListConverter())();
|
||||
BoolColumn get selected => boolean().withDefault(const Constant(false))();
|
||||
TextColumn get repository => text().nullable()();
|
||||
TextColumn get pluginApiVersion => text()();
|
||||
TextColumn get pluginApiVersion =>
|
||||
text().withDefault(const Constant('1.0.0'))();
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ class Sidebar extends HookConsumerWidget {
|
||||
color: Colors.black,
|
||||
borderRadius: BorderRadius.circular(50),
|
||||
),
|
||||
child: Assets.branding.spotubeLogo.image(
|
||||
child: Assets.branding.spotubeLogoPng.image(
|
||||
height: 50,
|
||||
cacheHeight: (100 * MediaQuery.devicePixelRatioOf(context)).toInt(),
|
||||
),
|
||||
|
@ -17,7 +17,7 @@ class GettingStartedPageGreetingSection extends HookConsumerWidget {
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Assets.branding.spotubeLogo.image(height: 200),
|
||||
Assets.branding.spotubeLogoPng.image(height: 200),
|
||||
const Gap(24),
|
||||
const Text("Spotube").semiBold().h4(),
|
||||
const Gap(4),
|
||||
|
@ -45,7 +45,7 @@ class HomePage extends HookConsumerWidget {
|
||||
floating: true,
|
||||
title: Image.asset(
|
||||
theme.brightness == Brightness.dark
|
||||
? Assets.branding.spotubeLogo.path
|
||||
? Assets.branding.spotubeLogoPng.path
|
||||
: Assets.branding.spotubeLogoLight.path,
|
||||
height: 45,
|
||||
width: 45,
|
||||
|
@ -45,7 +45,7 @@ class AboutSpotubePage extends HookConsumerWidget {
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
||||
child: Column(
|
||||
children: [
|
||||
Assets.branding.spotubeLogo.image(
|
||||
Assets.branding.spotubeLogoPng.image(
|
||||
height: 200,
|
||||
width: 200,
|
||||
),
|
||||
|
@ -348,7 +348,7 @@ class MetadataPluginNotifier extends AsyncNotifier<MetadataPluginState> {
|
||||
entryPoint: plugin.entryPoint,
|
||||
apis: plugin.apis.map((e) => e.name).toList(),
|
||||
abilities: plugin.abilities.map((e) => e.name).toList(),
|
||||
pluginApiVersion: plugin.pluginApiVersion,
|
||||
pluginApiVersion: Value(plugin.pluginApiVersion),
|
||||
repository: Value(plugin.repository),
|
||||
),
|
||||
);
|
||||
|
@ -27,7 +27,7 @@ abstract class FamilyPaginatedAsyncNotifier<K, A>
|
||||
final items = newState.items.isEmpty ? <K>[] : newState.items.cast<K>();
|
||||
|
||||
state = AsyncData(newState.copyWith(items: <K>[...oldItems, ...items]));
|
||||
} finally {
|
||||
} catch (e) {
|
||||
state = AsyncData(oldState!);
|
||||
}
|
||||
}
|
||||
@ -78,7 +78,7 @@ abstract class AutoDisposeFamilyPaginatedAsyncNotifier<K, A>
|
||||
...newState.items.cast<K>(),
|
||||
]),
|
||||
);
|
||||
} finally {
|
||||
} catch (e) {
|
||||
state = AsyncData(oldState!);
|
||||
}
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ mixin PaginatedAsyncNotifierMixin<K>
|
||||
final items = newState.items.isEmpty ? <K>[] : newState.items.cast<K>();
|
||||
|
||||
state = AsyncData(newState.copyWith(items: <K>[...oldItems, ...items]));
|
||||
} finally {
|
||||
} catch (e) {
|
||||
state = AsyncData(oldState!);
|
||||
}
|
||||
}
|
||||
|
@ -117,6 +117,24 @@ class ServerPlaybackRoutes {
|
||||
return dio.head(url, options: options);
|
||||
});
|
||||
|
||||
// Redirect to m3u8 link directly as it handles range requests internally
|
||||
if (contentLengthRes?.headers.value("content-type") ==
|
||||
"application/vnd.apple.mpegurl") {
|
||||
return (
|
||||
response: dio_lib.Response<Uint8List>(
|
||||
statusCode: 301,
|
||||
statusMessage: "M3U8 Redirect",
|
||||
headers: Headers.fromMap({
|
||||
"location": [url],
|
||||
"content-type": ["application/vnd.apple.mpegurl"],
|
||||
}),
|
||||
requestOptions: RequestOptions(path: request.requestedUri.toString()),
|
||||
isRedirect: true,
|
||||
),
|
||||
bytes: null,
|
||||
);
|
||||
}
|
||||
|
||||
final contentLength = contentLengthRes?.headers.value("content-length");
|
||||
|
||||
/// Forcing partial content range as mpv sometimes greedily wants
|
||||
|
@ -11,9 +11,7 @@ import 'package:http_parser/http_parser.dart';
|
||||
class YtDlpEngine implements YouTubeEngine {
|
||||
StreamManifest _parseFormats(List formats, videoId) {
|
||||
final audioOnlyStreams = formats
|
||||
.where(
|
||||
(f) => f["resolution"] == "audio only" && f["manifest_url"] == null,
|
||||
)
|
||||
.where((f) => f["resolution"] == "audio only")
|
||||
.sorted((a, b) => a["quality"] > b["quality"] ? 1 : -1)
|
||||
.map((f) {
|
||||
final filesize = f["filesize"] ?? f["filesize_approx"];
|
||||
@ -22,13 +20,14 @@ class YtDlpEngine implements YouTubeEngine {
|
||||
0,
|
||||
Uri.parse(f["url"]),
|
||||
StreamContainer.parse(
|
||||
f["container"]?.replaceAll("_dash", "").replaceAll("m4a", "mp4"),
|
||||
f["container"]?.replaceAll("_dash", "").replaceAll("m4a", "mp4") ??
|
||||
(f["protocol"] == "m3u8_native" ? "m3u8" : "mp4"),
|
||||
),
|
||||
filesize != null ? FileSize(filesize) : FileSize.unknown,
|
||||
Bitrate(
|
||||
(((f["abr"] ?? f["tbr"] ?? 0) * 1000) as num).toInt(),
|
||||
),
|
||||
f["acodec"] ?? "webm",
|
||||
f["acodec"] ?? "aac",
|
||||
f["format_note"],
|
||||
[],
|
||||
MediaType.parse(
|
||||
|
@ -27,6 +27,8 @@ PODS:
|
||||
- flutter_timezone (0.1.0):
|
||||
- FlutterMacOS
|
||||
- FlutterMacOS (1.0.0)
|
||||
- irondash_engine_context (0.0.1):
|
||||
- FlutterMacOS
|
||||
- local_notifier (0.1.0):
|
||||
- FlutterMacOS
|
||||
- media_kit_libs_macos_audio (1.0.4):
|
||||
@ -70,6 +72,8 @@ PODS:
|
||||
- sqlite3/fts5
|
||||
- sqlite3/perf-threadsafe
|
||||
- sqlite3/rtree
|
||||
- super_native_extensions (0.0.1):
|
||||
- FlutterMacOS
|
||||
- system_theme (0.0.1):
|
||||
- FlutterMacOS
|
||||
- tray_manager (0.0.1):
|
||||
@ -93,6 +97,7 @@ DEPENDENCIES:
|
||||
- flutter_secure_storage_macos (from `Flutter/ephemeral/.symlinks/plugins/flutter_secure_storage_macos/macos`)
|
||||
- flutter_timezone (from `Flutter/ephemeral/.symlinks/plugins/flutter_timezone/macos`)
|
||||
- FlutterMacOS (from `Flutter/ephemeral`)
|
||||
- irondash_engine_context (from `Flutter/ephemeral/.symlinks/plugins/irondash_engine_context/macos`)
|
||||
- local_notifier (from `Flutter/ephemeral/.symlinks/plugins/local_notifier/macos`)
|
||||
- media_kit_libs_macos_audio (from `Flutter/ephemeral/.symlinks/plugins/media_kit_libs_macos_audio/macos`)
|
||||
- media_kit_native_event_loop (from `Flutter/ephemeral/.symlinks/plugins/media_kit_native_event_loop/macos`)
|
||||
@ -104,6 +109,7 @@ DEPENDENCIES:
|
||||
- shared_preferences_foundation (from `Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin`)
|
||||
- sqflite_darwin (from `Flutter/ephemeral/.symlinks/plugins/sqflite_darwin/darwin`)
|
||||
- sqlite3_flutter_libs (from `Flutter/ephemeral/.symlinks/plugins/sqlite3_flutter_libs/darwin`)
|
||||
- super_native_extensions (from `Flutter/ephemeral/.symlinks/plugins/super_native_extensions/macos`)
|
||||
- system_theme (from `Flutter/ephemeral/.symlinks/plugins/system_theme/macos`)
|
||||
- tray_manager (from `Flutter/ephemeral/.symlinks/plugins/tray_manager/macos`)
|
||||
- url_launcher_macos (from `Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos`)
|
||||
@ -141,6 +147,8 @@ EXTERNAL SOURCES:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/flutter_timezone/macos
|
||||
FlutterMacOS:
|
||||
:path: Flutter/ephemeral
|
||||
irondash_engine_context:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/irondash_engine_context/macos
|
||||
local_notifier:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/local_notifier/macos
|
||||
media_kit_libs_macos_audio:
|
||||
@ -163,6 +171,8 @@ EXTERNAL SOURCES:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/sqflite_darwin/darwin
|
||||
sqlite3_flutter_libs:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/sqlite3_flutter_libs/darwin
|
||||
super_native_extensions:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/super_native_extensions/macos
|
||||
system_theme:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/system_theme/macos
|
||||
tray_manager:
|
||||
@ -185,7 +195,8 @@ SPEC CHECKSUMS:
|
||||
flutter_inappwebview_macos: c2d68649f9f8f1831bfcd98d73fd6256366d9d1d
|
||||
flutter_secure_storage_macos: 7f45e30f838cf2659862a4e4e3ee1c347c2b3b54
|
||||
flutter_timezone: d59eea86178cbd7943cd2431cc2eaa9850f935d8
|
||||
FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24
|
||||
FlutterMacOS: d0db08ddef1a9af05a5ec4b724367152bb0500b1
|
||||
irondash_engine_context: 893c7d96d20ce361d7e996f39d360c4c2f9869ba
|
||||
local_notifier: ebf072651e35ae5e47280ad52e2707375cb2ae4e
|
||||
media_kit_libs_macos_audio: 06f3cf88d6d89c7c3c87eae57689d1c6adb335b2
|
||||
media_kit_native_event_loop: a5833d1e4d5bedb6f691e9909fa57f15f436f2c8
|
||||
@ -199,6 +210,7 @@ SPEC CHECKSUMS:
|
||||
sqflite_darwin: 20b2a3a3b70e43edae938624ce550a3cbf66a3d0
|
||||
sqlite3: 7559e33dae4c78538df563795af3a86fc887ee71
|
||||
sqlite3_flutter_libs: f0b59f6bb2a18597d0796558725007e5a7428397
|
||||
super_native_extensions: c2795d6d9aedf4a79fae25cb6160b71b50549189
|
||||
system_theme: ed74293ad07d3a05e3e2d0059ff342360346f1a0
|
||||
tray_manager: a104b5c81b578d83f3c3d0f40a997c8b10810166
|
||||
url_launcher_macos: 0fba8ddabfc33ce0a9afe7c5fef5aab3d8d2d673
|
||||
|
@ -410,7 +410,7 @@
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.14;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.15;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = macosx;
|
||||
SWIFT_COMPILATION_MODE = wholemodule;
|
||||
@ -494,7 +494,7 @@
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.14;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.15;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = macosx;
|
||||
@ -541,7 +541,7 @@
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.14;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.15;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = macosx;
|
||||
SWIFT_COMPILATION_MODE = wholemodule;
|
||||
|
@ -2881,8 +2881,8 @@ packages:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
path: "."
|
||||
ref: e2d82305fab18566408d6f8758361017d1640c3d
|
||||
resolved-ref: e2d82305fab18566408d6f8758361017d1640c3d
|
||||
ref: "4e5310e14af74bdbb51e2a4766e66d6c6a2562a8"
|
||||
resolved-ref: "4e5310e14af74bdbb51e2a4766e66d6c6a2562a8"
|
||||
url: "https://github.com/KRTirtho/yt_dlp_dart.git"
|
||||
source: git
|
||||
version: "1.0.0"
|
||||
|
@ -132,7 +132,7 @@ dependencies:
|
||||
yt_dlp_dart:
|
||||
git:
|
||||
url: https://github.com/KRTirtho/yt_dlp_dart.git
|
||||
ref: e2d82305fab18566408d6f8758361017d1640c3d
|
||||
ref: 4e5310e14af74bdbb51e2a4766e66d6c6a2562a8
|
||||
flutter_new_pipe_extractor:
|
||||
git:
|
||||
url: https://github.com/KRTirtho/flutter_new_pipe_extractor.git
|
||||
@ -203,6 +203,7 @@ flutter:
|
||||
- assets/images/logos/
|
||||
- assets/branding/spotube-logo.png
|
||||
- assets/branding/spotube-logo-light.png
|
||||
- assets/branding/spotube-logo.ico
|
||||
- LICENSE
|
||||
- packages/flutter_undraw/assets/undraw/access_denied.svg
|
||||
- packages/flutter_undraw/assets/undraw/fixing_bugs.svg
|
||||
|
@ -1,38 +1,41 @@
|
||||
// dart format width=80
|
||||
// GENERATED CODE, DO NOT EDIT BY HAND.
|
||||
// ignore_for_file: type=lint
|
||||
//@dart=2.12
|
||||
import 'package:drift/drift.dart';
|
||||
import 'package:drift/internal/migrations.dart';
|
||||
import 'schema_v1.dart' as v1;
|
||||
import 'schema_v2.dart' as v2;
|
||||
import 'schema_v3.dart' as v3;
|
||||
import 'schema_v4.dart' as v4;
|
||||
import 'schema_v5.dart' as v5;
|
||||
import 'schema_v6.dart' as v6;
|
||||
import 'schema_v4.dart' as v4;
|
||||
import 'schema_v8.dart' as v8;
|
||||
import 'schema_v3.dart' as v3;
|
||||
import 'schema_v2.dart' as v2;
|
||||
import 'schema_v1.dart' as v1;
|
||||
import 'schema_v7.dart' as v7;
|
||||
import 'schema_v6.dart' as v6;
|
||||
|
||||
class GeneratedHelper implements SchemaInstantiationHelper {
|
||||
@override
|
||||
GeneratedDatabase databaseForVersion(QueryExecutor db, int version) {
|
||||
switch (version) {
|
||||
case 1:
|
||||
return v1.DatabaseAtV1(db);
|
||||
case 2:
|
||||
return v2.DatabaseAtV2(db);
|
||||
case 3:
|
||||
return v3.DatabaseAtV3(db);
|
||||
case 4:
|
||||
return v4.DatabaseAtV4(db);
|
||||
case 5:
|
||||
return v5.DatabaseAtV5(db);
|
||||
case 6:
|
||||
return v6.DatabaseAtV6(db);
|
||||
case 4:
|
||||
return v4.DatabaseAtV4(db);
|
||||
case 8:
|
||||
return v8.DatabaseAtV8(db);
|
||||
case 3:
|
||||
return v3.DatabaseAtV3(db);
|
||||
case 2:
|
||||
return v2.DatabaseAtV2(db);
|
||||
case 1:
|
||||
return v1.DatabaseAtV1(db);
|
||||
case 7:
|
||||
return v7.DatabaseAtV7(db);
|
||||
case 6:
|
||||
return v6.DatabaseAtV6(db);
|
||||
default:
|
||||
throw MissingSchemaException(version, versions);
|
||||
}
|
||||
}
|
||||
|
||||
static const versions = const [1, 2, 3, 4, 5, 6, 7];
|
||||
static const versions = const [1, 2, 3, 4, 5, 6, 7, 8];
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
// dart format width=80
|
||||
// GENERATED CODE, DO NOT EDIT BY HAND.
|
||||
// ignore_for_file: type=lint
|
||||
//@dart=2.12
|
||||
import 'package:drift/drift.dart';
|
||||
|
||||
class AuthenticationTable extends Table
|
||||
|
@ -1,6 +1,6 @@
|
||||
// dart format width=80
|
||||
// GENERATED CODE, DO NOT EDIT BY HAND.
|
||||
// ignore_for_file: type=lint
|
||||
//@dart=2.12
|
||||
import 'package:drift/drift.dart';
|
||||
|
||||
class AuthenticationTable extends Table
|
||||
|
@ -1,6 +1,6 @@
|
||||
// dart format width=80
|
||||
// GENERATED CODE, DO NOT EDIT BY HAND.
|
||||
// ignore_for_file: type=lint
|
||||
//@dart=2.12
|
||||
import 'package:drift/drift.dart';
|
||||
|
||||
class AuthenticationTable extends Table
|
||||
|
@ -1,6 +1,6 @@
|
||||
// dart format width=80
|
||||
// GENERATED CODE, DO NOT EDIT BY HAND.
|
||||
// ignore_for_file: type=lint
|
||||
//@dart=2.12
|
||||
import 'package:drift/drift.dart';
|
||||
|
||||
class AuthenticationTable extends Table
|
||||
|
@ -1,6 +1,6 @@
|
||||
// dart format width=80
|
||||
// GENERATED CODE, DO NOT EDIT BY HAND.
|
||||
// ignore_for_file: type=lint
|
||||
//@dart=2.12
|
||||
import 'package:drift/drift.dart';
|
||||
|
||||
class AuthenticationTable extends Table
|
||||
|
@ -1,6 +1,6 @@
|
||||
// dart format width=80
|
||||
// GENERATED CODE, DO NOT EDIT BY HAND.
|
||||
// ignore_for_file: type=lint
|
||||
//@dart=2.12
|
||||
import 'package:drift/drift.dart';
|
||||
|
||||
class AuthenticationTable extends Table
|
||||
|
@ -1,6 +1,6 @@
|
||||
// dart format width=80
|
||||
// GENERATED CODE, DO NOT EDIT BY HAND.
|
||||
// ignore_for_file: type=lint
|
||||
//@dart=2.12
|
||||
import 'package:drift/drift.dart';
|
||||
|
||||
class AuthenticationTable extends Table
|
||||
|
3517
test/drift/app_db/generated/schema_v8.dart
Normal file
3517
test/drift/app_db/generated/schema_v8.dart
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user