Compare commits
1782 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
a8f70f201e | ||
![]() |
b8ecd758cf | ||
![]() |
70970f62f1 | ||
![]() |
4ed40d95b2 | ||
![]() |
b24dcd2951 | ||
![]() |
8ff90bafd7 | ||
![]() |
9190af92ef | ||
![]() |
151a440e7e | ||
![]() |
9471e008e3 | ||
![]() |
ecc0bdcc42 | ||
![]() |
49c04af302 | ||
![]() |
afe0bea306 | ||
![]() |
eadf2d928f | ||
![]() |
a299a97ca4 | ||
![]() |
cbbd0a2b40 | ||
![]() |
216fdadf25 | ||
![]() |
3599a4340f | ||
![]() |
719229b2b7 | ||
![]() |
49db82083c | ||
![]() |
84f119e482 | ||
![]() |
aeb8caf059 | ||
![]() |
7c4956153a | ||
![]() |
58dc80aa09 | ||
![]() |
4a07945214 | ||
![]() |
7b21eca37b | ||
![]() |
43ddf90c48 | ||
![]() |
878a441a9f | ||
![]() |
90493f0ea3 | ||
![]() |
db22b4fcce | ||
![]() |
0d6d482630 | ||
![]() |
a4162dc2ad | ||
![]() |
469a76dbd6 | ||
![]() |
6940e92142 | ||
![]() |
4d57b134a3 | ||
![]() |
a370166576 | ||
![]() |
69d50eec35 | ||
![]() |
2e48ac380b | ||
![]() |
d22b5349a3 | ||
![]() |
83172f198c | ||
![]() |
f870e12011 | ||
![]() |
345c6ac714 | ||
![]() |
005355e267 | ||
![]() |
aee2c9282d | ||
![]() |
ea329f40e8 | ||
![]() |
b248f90403 | ||
![]() |
e2c0ddef24 | ||
![]() |
2a0853026a | ||
![]() |
dddaa5a964 | ||
![]() |
412f3dd81c | ||
![]() |
7f30ae8d31 | ||
![]() |
c0d50d441e | ||
![]() |
66cae6c7ac | ||
![]() |
308c417ed3 | ||
![]() |
0823629fb5 | ||
![]() |
7037145519 | ||
![]() |
08d1c98674 | ||
![]() |
c0dcc87eb2 | ||
![]() |
b4f8d2dfbf | ||
![]() |
48490cf168 | ||
![]() |
ea7138e95b | ||
![]() |
5add53e269 | ||
![]() |
c615d48e27 | ||
![]() |
92c05a51e1 | ||
![]() |
71bcf355ec | ||
![]() |
089a3445a1 | ||
![]() |
dbba55606b | ||
![]() |
a2894db652 | ||
![]() |
edcd784335 | ||
![]() |
0a153fe770 | ||
![]() |
3f18f35c0b | ||
![]() |
30fd4acf37 | ||
![]() |
0e34057794 | ||
![]() |
032309a2c6 | ||
![]() |
858cbd17ad | ||
![]() |
fbd7b771ef | ||
![]() |
8bdbe7dfba | ||
![]() |
b3f6824a94 | ||
![]() |
7bb69c02de | ||
![]() |
a734ded6f8 | ||
![]() |
f228937e3e | ||
![]() |
ee7d0cfeb5 | ||
![]() |
7a630507fb | ||
![]() |
dffd494d4a | ||
![]() |
49e2d1b759 | ||
![]() |
fd3ddfece9 | ||
![]() |
2bb91feb34 | ||
![]() |
eb3fcfdd6f | ||
![]() |
066fe2a326 | ||
![]() |
93d6e0642b | ||
![]() |
1e61bca1e9 | ||
![]() |
3bb7f0d78f | ||
![]() |
75bdbeccc0 | ||
![]() |
846fa679f6 | ||
![]() |
3a5ddd6214 | ||
![]() |
3b21b05fdc | ||
![]() |
53ef9e15e1 | ||
![]() |
7309e900bc | ||
![]() |
c9556c2ecb | ||
![]() |
efdf091894 | ||
![]() |
92dde7286f | ||
![]() |
0a604a9ad5 | ||
![]() |
cfda46e07e | ||
![]() |
60f032039f | ||
![]() |
d2e0dc1ac9 | ||
![]() |
3e7b36f4e6 | ||
![]() |
cdc64e4bb0 | ||
![]() |
2f304fa943 | ||
![]() |
e83a4bb388 | ||
![]() |
90f9cc28eb | ||
![]() |
f23a078b64 | ||
![]() |
d2827a52d3 | ||
![]() |
7de6423935 | ||
![]() |
5573deb52a | ||
![]() |
412c427cec | ||
![]() |
5be4747c66 | ||
![]() |
5b457fc4bd | ||
![]() |
cb97f4352c | ||
![]() |
ee71dbf552 | ||
![]() |
1538dc6d52 | ||
![]() |
53ad5bd448 | ||
![]() |
aa65bf291d | ||
![]() |
41cc79b5e6 | ||
![]() |
86e55f7a3d | ||
![]() |
1eb0b5f847 | ||
![]() |
d898d45b4a | ||
![]() |
5f47dc3d6d | ||
![]() |
4e6db8b9e1 | ||
![]() |
b979a6ede9 | ||
![]() |
fcc05a4243 | ||
![]() |
7569c37739 | ||
![]() |
b8cae569b4 | ||
![]() |
4b09f6c96b | ||
![]() |
758b0bc9d9 | ||
![]() |
326d8212f6 | ||
![]() |
a9ba2582fb | ||
![]() |
f8211cbcc7 | ||
![]() |
3306f21860 | ||
![]() |
7a6821f28d | ||
![]() |
69c0333327 | ||
![]() |
2d6fe886e2 | ||
![]() |
67713c60d4 | ||
![]() |
bb0afa5a0c | ||
![]() |
f4306ad1c3 | ||
![]() |
b9c6c98e38 | ||
![]() |
0326630a19 | ||
![]() |
abe04b28b2 | ||
![]() |
8ac30c0031 | ||
![]() |
9a861b9954 | ||
![]() |
7491175bb6 | ||
![]() |
a65846d15e | ||
![]() |
4f72f3b424 | ||
![]() |
ecb43f64ad | ||
![]() |
e575d23c4a | ||
![]() |
76f0f18592 | ||
![]() |
ae0f24d34a | ||
![]() |
a06614bc5c | ||
![]() |
7c26d29d06 | ||
![]() |
b6c0926efc | ||
![]() |
89cf73d95f | ||
![]() |
e6a9011c5c | ||
![]() |
7143913bba | ||
![]() |
5567214588 | ||
![]() |
5ff1fc9f82 | ||
![]() |
d3edf07ac9 | ||
![]() |
8fc319d980 | ||
![]() |
e986baa0aa | ||
![]() |
8a7f5c4008 | ||
![]() |
9d2ad1c626 | ||
![]() |
b74c2eab8f | ||
![]() |
2c4cc94985 | ||
![]() |
ba27dc70e4 | ||
![]() |
0ec9f3535b | ||
![]() |
df72ba6960 | ||
![]() |
d9057dae57 | ||
![]() |
e61b79585e | ||
![]() |
a9e5636e96 | ||
![]() |
723b6b1f38 | ||
![]() |
764950b286 | ||
![]() |
290affd435 | ||
![]() |
c59b5c651e | ||
![]() |
e4ac7cacc9 | ||
![]() |
26b1c31f8f | ||
![]() |
4bfe334419 | ||
![]() |
48fcfbc928 | ||
![]() |
95e09ffc94 | ||
![]() |
968fd09eb3 | ||
![]() |
1a32264bc7 | ||
![]() |
59f298a935 | ||
![]() |
bbe3394e9e | ||
![]() |
7cde803bee | ||
![]() |
cd475e93d0 | ||
![]() |
3d334d96fd | ||
![]() |
bd4cd22e4e | ||
![]() |
c709de6bf1 | ||
![]() |
ccbac85171 | ||
![]() |
50123b235c | ||
![]() |
4072531c62 | ||
![]() |
464666c01a | ||
![]() |
4db9a95a91 | ||
![]() |
0e58cd0e99 | ||
![]() |
3cce2868de | ||
![]() |
894b0d7e5e | ||
![]() |
7befbca8e5 | ||
![]() |
d4f70f56e4 | ||
![]() |
180d07a1be | ||
![]() |
91871d0d26 | ||
![]() |
c3bbc129ad | ||
![]() |
a9586a64f2 | ||
![]() |
677f95f266 | ||
![]() |
f4b1e550bf | ||
![]() |
bb71fc0eea | ||
![]() |
7eb0e69dd7 | ||
![]() |
30bf0bed62 | ||
![]() |
c82b68a513 | ||
![]() |
edc9636940 | ||
![]() |
47edb8bf96 | ||
![]() |
e8e2d78529 | ||
![]() |
0248dd3c23 | ||
![]() |
1e6d709e04 | ||
![]() |
698fb6ba27 | ||
![]() |
043eaba81f | ||
![]() |
b1780e0cf8 | ||
![]() |
cd39bbf87c | ||
![]() |
d4504722d8 | ||
![]() |
6ddf6b9cce | ||
![]() |
4b2d259add | ||
![]() |
0037677383 | ||
![]() |
2b0b5eae1d | ||
![]() |
6cf4ca9179 | ||
![]() |
2ea8070771 | ||
![]() |
e0760e6250 | ||
![]() |
ada0ca1472 | ||
![]() |
42158a99ff | ||
![]() |
5c6cb770a8 | ||
![]() |
4c3718467d | ||
![]() |
4e8a50ec58 | ||
![]() |
75e189344e | ||
![]() |
8c0a47374d | ||
![]() |
697ba1ed7b | ||
![]() |
e05645c46e | ||
![]() |
ee95b3b26a | ||
![]() |
b2b38a9191 | ||
![]() |
219ae9dcb3 | ||
![]() |
ed1f4ad6f5 | ||
![]() |
15773e1ce7 | ||
![]() |
b7bb35d299 | ||
![]() |
1937b1b840 | ||
![]() |
85ebaf69de | ||
![]() |
becba8956f | ||
![]() |
343198a7e8 | ||
![]() |
0aee8b3399 | ||
![]() |
768bab8bbb | ||
![]() |
082f711018 | ||
![]() |
6e357230ac | ||
![]() |
2411f46877 | ||
![]() |
4fead5f504 | ||
![]() |
086107b2cd | ||
![]() |
74a328e529 | ||
![]() |
e470f50e81 | ||
![]() |
6c005592e3 | ||
![]() |
696875e4b5 | ||
![]() |
5930c342b5 | ||
![]() |
3649b67869 | ||
![]() |
b8ffb9b75f | ||
![]() |
a8694a7a8b | ||
![]() |
b25ae332b8 | ||
![]() |
5a14f587a0 | ||
![]() |
2daea2b3ef | ||
![]() |
88906098dd | ||
![]() |
e54a646073 | ||
![]() |
3ffcb48db9 | ||
![]() |
46852545a9 | ||
![]() |
bf94a490bb | ||
![]() |
6dd9b753b0 | ||
![]() |
e6408ccc0d | ||
![]() |
dff8fe2e64 | ||
![]() |
b734985199 | ||
![]() |
dd0bb01af5 | ||
![]() |
b8f2495acb | ||
![]() |
4afe0cca68 | ||
![]() |
bbad701c07 | ||
![]() |
af295be8c6 | ||
![]() |
780f5dee2e | ||
![]() |
30e03786bf | ||
![]() |
f96b5eae97 | ||
![]() |
684e595d16 | ||
![]() |
047eccfa82 | ||
![]() |
b558cc17f1 | ||
![]() |
d845180e60 | ||
![]() |
2ee0ca44c7 | ||
![]() |
d53782da23 | ||
![]() |
ced85d3f0c | ||
![]() |
e2143a0625 | ||
![]() |
db3aaa4b83 | ||
![]() |
ccf84c568e | ||
![]() |
fdb5ed8f56 | ||
![]() |
b40c0b7772 | ||
![]() |
b09263d128 | ||
![]() |
a6720d5392 | ||
![]() |
05d544fe5a | ||
![]() |
2fefd65f51 | ||
![]() |
7ee071f2e3 | ||
![]() |
418a0d29bd | ||
![]() |
2925dd6748 | ||
![]() |
f80ea32de4 | ||
![]() |
fcefce4b1b | ||
![]() |
1089e90511 | ||
![]() |
2488da2279 | ||
![]() |
04190f2dda | ||
![]() |
fe2f0a373f | ||
![]() |
e73d2d06d8 | ||
![]() |
5ad151932a | ||
![]() |
b52bf0f448 | ||
![]() |
55871e3cdd | ||
![]() |
0aa44520ac | ||
![]() |
4595eb169f | ||
![]() |
08f624ece1 | ||
![]() |
f524a40062 | ||
![]() |
f28fe5a682 | ||
![]() |
efa2b77ac3 | ||
![]() |
12f3ec1776 | ||
![]() |
8c1337d1fc | ||
![]() |
b32ec667a9 | ||
![]() |
18a68d85a5 | ||
![]() |
2d972c8f57 | ||
![]() |
083b366308 | ||
![]() |
8ca2115ef0 | ||
![]() |
499ecfba26 | ||
![]() |
3fd7a18159 | ||
![]() |
e3285bd4da | ||
![]() |
9f2d423cfe | ||
![]() |
3c45732b0a | ||
![]() |
cab61631ef | ||
![]() |
6e1cd96903 | ||
![]() |
9cd839cfd9 | ||
![]() |
94e704087f | ||
![]() |
f553e43b17 | ||
![]() |
8e287ab1e5 | ||
![]() |
fdde972a77 | ||
![]() |
8c5ece5335 | ||
![]() |
a76b5c4c7f | ||
![]() |
70bbb4af5a | ||
![]() |
2a317397ee | ||
![]() |
4e0de13075 | ||
![]() |
58f6142d2f | ||
![]() |
9c80c610b4 | ||
![]() |
b87a51011b | ||
![]() |
34d8bc26fe | ||
![]() |
c1f2ddcdbe | ||
![]() |
200ee4a6bd | ||
![]() |
ce9627218d | ||
![]() |
142d6884c3 | ||
![]() |
ee8406772c | ||
![]() |
87a78549b6 | ||
![]() |
5ac534619f | ||
![]() |
68ca6a7d31 | ||
![]() |
7f23c9f8f6 | ||
![]() |
c9d6d2cd48 | ||
![]() |
c680aeb1f4 | ||
![]() |
4618a6406c | ||
![]() |
02818593ed | ||
![]() |
1cad097d0b | ||
![]() |
57c8f85731 | ||
![]() |
1119c0e47d | ||
![]() |
5ff36a8643 | ||
![]() |
9cb828bb55 | ||
![]() |
36d161c05a | ||
![]() |
959199ff84 | ||
![]() |
33ecbe066c | ||
![]() |
29015bca76 | ||
![]() |
3afe3cea80 | ||
![]() |
40bfcc1961 | ||
![]() |
4f882882e0 | ||
![]() |
efada35ce0 | ||
![]() |
2d4c9cabd2 | ||
![]() |
6d0cbf97e3 | ||
![]() |
4385f2f472 | ||
![]() |
d50e60e2b2 | ||
![]() |
aa5d0e535b | ||
![]() |
af60cfc067 | ||
![]() |
411115327d | ||
![]() |
9a0421ce38 | ||
![]() |
6d9361f3fe | ||
![]() |
95ff13324e | ||
![]() |
470addca83 | ||
![]() |
9294858fb6 | ||
![]() |
9b02412060 | ||
![]() |
a5e02d068e | ||
![]() |
b501078c43 | ||
![]() |
d0a225d0b1 | ||
![]() |
2be84ec4ee | ||
![]() |
c681401b6e | ||
![]() |
1b024b41fe | ||
![]() |
b0a07b58d5 | ||
![]() |
b32ec9ccf9 | ||
![]() |
9b7a7ef1cf | ||
![]() |
7408a87860 | ||
![]() |
95b68687d5 | ||
![]() |
388e2d0289 | ||
![]() |
84f47df6c1 | ||
![]() |
64d25509b4 | ||
![]() |
6456b43d10 | ||
![]() |
123eb168a3 | ||
![]() |
56ce84d748 | ||
![]() |
39ea7a701c | ||
![]() |
1cc7882177 | ||
![]() |
ebaf5615ad | ||
![]() |
ce19ef1efd | ||
![]() |
1c66646798 | ||
![]() |
b5f3894983 | ||
![]() |
0465042264 | ||
![]() |
4b65319879 | ||
![]() |
0d537abab3 | ||
![]() |
d515f3d3be | ||
![]() |
0eb78d14ca | ||
![]() |
b211813213 | ||
![]() |
bd511584e7 | ||
![]() |
0d9fb1d388 | ||
![]() |
9b05b8adf1 | ||
![]() |
1441736627 | ||
![]() |
a2ba46ea45 | ||
![]() |
e6fee03c20 | ||
![]() |
6a500731d6 | ||
![]() |
a6e13ffc08 | ||
![]() |
d22bba5393 | ||
![]() |
abfdbc63ce | ||
![]() |
00f1b3422f | ||
![]() |
7a31119e3c | ||
![]() |
44861a9f5c | ||
![]() |
c7d8ed567a | ||
![]() |
67ae2e8159 | ||
![]() |
d359d130de | ||
![]() |
86ee64c606 | ||
![]() |
15211123aa | ||
![]() |
243a843033 | ||
![]() |
86f5b80177 | ||
![]() |
ccea4a003d | ||
![]() |
2ce4853fd1 | ||
![]() |
2f46fa32f1 | ||
![]() |
359b918e6b | ||
![]() |
7dd76d24c3 | ||
![]() |
f2f35bd2fb | ||
![]() |
79b842dad3 | ||
![]() |
1284b409e7 | ||
![]() |
15bd58a955 | ||
![]() |
cb6b6f142e | ||
![]() |
7927a3e404 | ||
![]() |
3bdc46da4d | ||
![]() |
4c5564fd2f | ||
![]() |
261e1b6685 | ||
![]() |
ffb3a3377f | ||
![]() |
a3021e4c52 | ||
![]() |
1cfd377c29 | ||
![]() |
b495ed4ac0 | ||
![]() |
08ac29c979 | ||
![]() |
44418868ad | ||
![]() |
6c5cab9899 | ||
![]() |
1b420e661b | ||
![]() |
a621a45f0b | ||
![]() |
75173e5096 | ||
![]() |
a83dd64476 | ||
![]() |
f79fedefd4 | ||
![]() |
59041a2948 | ||
![]() |
5936f08a92 | ||
![]() |
b9b7d5c8aa | ||
![]() |
d18f74fd65 | ||
![]() |
a799ca55bc | ||
![]() |
bf6cec8d69 | ||
![]() |
52d4f60ccc | ||
![]() |
3fb003ea60 | ||
![]() |
a35eece00c | ||
![]() |
2540d16ced | ||
![]() |
9034ee29db | ||
![]() |
064d92d35d | ||
![]() |
cb8d24ff31 | ||
![]() |
4f2175987d | ||
![]() |
6067314c5a | ||
![]() |
9ce911a8ab | ||
![]() |
2822d5dbfd | ||
![]() |
de61d90938 | ||
![]() |
f9087b63d5 | ||
![]() |
d115e57058 | ||
![]() |
7816cb8068 | ||
![]() |
8cb6c6d126 | ||
![]() |
4af23241c8 | ||
![]() |
b224af21ea | ||
![]() |
1cfeef54e7 | ||
![]() |
f81219e83e | ||
![]() |
63bf694d5c | ||
![]() |
9c3f9733b5 | ||
![]() |
eea8fd1579 | ||
![]() |
73bd207ce2 | ||
![]() |
491c1b9857 | ||
![]() |
e223a10bde | ||
![]() |
a9c78b7863 | ||
![]() |
bf769f473b | ||
![]() |
6c6488ea6d | ||
![]() |
47f98b98aa | ||
![]() |
5f280a19f4 | ||
![]() |
6591ec0e1b | ||
![]() |
d7d864ff2b | ||
![]() |
3394c1b057 | ||
![]() |
6cb29868d2 | ||
![]() |
37d002d133 | ||
![]() |
73c5b30b63 | ||
![]() |
982cf0bd43 | ||
![]() |
57cd8607dd | ||
![]() |
26ee84d990 | ||
![]() |
8fc44ed655 | ||
![]() |
ed48d25add | ||
![]() |
2b5fd35529 | ||
![]() |
3aca7372af | ||
![]() |
ab713a4eac | ||
![]() |
9cd44b6c9b | ||
![]() |
f6ba95fb64 | ||
![]() |
c3c9fc544c | ||
![]() |
bc534aa240 | ||
![]() |
e63a4bb63c | ||
![]() |
c607a330ed | ||
![]() |
56241f773a | ||
![]() |
71341ec0bd | ||
![]() |
02acbd9327 | ||
![]() |
c4023aa09d | ||
![]() |
e034455173 | ||
![]() |
e1786989ff | ||
![]() |
b2d9e64758 | ||
![]() |
d2683c52d8 | ||
![]() |
82307bc030 | ||
![]() |
fc5bfa089c | ||
![]() |
d82261cb25 | ||
![]() |
22caa818f4 | ||
![]() |
9aea35468f | ||
![]() |
8fad2251b3 | ||
![]() |
bf45681deb | ||
![]() |
0280654bb6 | ||
![]() |
edc997e747 | ||
![]() |
1e7f0e1fe7 | ||
![]() |
dbc1c452dd | ||
![]() |
2b01e4fb4d | ||
![]() |
a838eadc12 | ||
![]() |
a77b6776e8 | ||
![]() |
4ca893950b | ||
![]() |
2286277a06 | ||
![]() |
c1a105a1ff | ||
![]() |
7ad67fa3fa | ||
![]() |
937a706ac9 | ||
![]() |
88fea7ecf9 | ||
![]() |
ef7833eb67 | ||
![]() |
2da5d786d2 | ||
![]() |
9bccbc93c6 | ||
![]() |
7e07c2e198 | ||
![]() |
7ac791757a | ||
![]() |
6907f9c756 | ||
![]() |
930539ca48 | ||
![]() |
cb95663412 | ||
![]() |
883783b769 | ||
![]() |
7ae9f56482 | ||
![]() |
5a6b800912 | ||
![]() |
6f4c308457 | ||
![]() |
6e07fec1a5 | ||
![]() |
9e25c742d4 | ||
![]() |
9791e3fb5f | ||
![]() |
2d1f4b9380 | ||
![]() |
39e97eef34 | ||
![]() |
f82253c6ba | ||
![]() |
57ccf16311 | ||
![]() |
2781127da1 | ||
![]() |
6e41b106fa | ||
![]() |
22a49e56a2 | ||
![]() |
b948872258 | ||
![]() |
17837f4149 | ||
![]() |
4b757d8e8d | ||
![]() |
27604b28f2 | ||
![]() |
beafe23e30 | ||
![]() |
ca546bef17 | ||
![]() |
2abb5800be | ||
![]() |
392047247b | ||
![]() |
9391e7a379 | ||
![]() |
b70f250e8d | ||
![]() |
de68fe3a6b | ||
![]() |
0d080b77b7 | ||
![]() |
f26503990c | ||
![]() |
5afe823abd | ||
![]() |
c8dd8025ec | ||
![]() |
68374efd3e | ||
![]() |
044d3b4820 | ||
![]() |
ee97aedcfc | ||
![]() |
82b1cfa0d7 | ||
![]() |
e99f32b610 | ||
![]() |
9f96b5c537 | ||
![]() |
1a6cea926f | ||
![]() |
1cea95bbda | ||
![]() |
7545ff6415 | ||
![]() |
6673e5a8a8 | ||
![]() |
f4dce2f611 | ||
![]() |
35e9920b51 | ||
![]() |
f37ac06e1a | ||
![]() |
ca2b81d572 | ||
![]() |
6539009629 | ||
![]() |
97ecaca9d9 | ||
![]() |
eec7a9dbc4 | ||
![]() |
e516afb185 | ||
![]() |
a248a4b48c | ||
![]() |
4a044498a4 | ||
![]() |
389a4fc704 | ||
![]() |
a6164c5791 | ||
![]() |
5019c14c44 | ||
![]() |
b354f57d4e | ||
![]() |
ca76a39910 | ||
![]() |
57ac3177c0 | ||
![]() |
60f2911eb9 | ||
![]() |
0742e898e3 | ||
![]() |
06a7ecf393 | ||
![]() |
88c6822555 | ||
![]() |
bda76a59ec | ||
![]() |
d1f0e778f6 | ||
![]() |
d0f6f9d9f6 | ||
![]() |
fdea9307bb | ||
![]() |
af1ce932a1 | ||
![]() |
649d6acfe2 | ||
![]() |
2c0b1a57e5 | ||
![]() |
f09ab004bf | ||
![]() |
09fac66d26 | ||
![]() |
b0970090b1 | ||
![]() |
a9a1d4c9dc | ||
![]() |
e6a20b5a16 | ||
![]() |
0ae6af61c9 | ||
![]() |
761d968ceb | ||
![]() |
019ba865e2 | ||
![]() |
27e7d532f0 | ||
![]() |
befaf59f0c | ||
![]() |
920d4219f0 | ||
![]() |
59a819be9c | ||
![]() |
1fa6d1f819 | ||
![]() |
4d6af8c0a7 | ||
![]() |
17105a640b | ||
![]() |
a850ed270b | ||
![]() |
96a2a1f5a6 | ||
![]() |
ca71406505 | ||
![]() |
9095a8c8f8 | ||
![]() |
6f71e52ea8 | ||
![]() |
87e203b8b4 | ||
![]() |
095587ee84 | ||
![]() |
846ae82084 | ||
![]() |
ab08c82c8d | ||
![]() |
b6d42659b7 | ||
![]() |
ba69496dcc | ||
![]() |
6f8271f5e9 | ||
![]() |
3294f657fe | ||
![]() |
c3289a0ba4 | ||
![]() |
86123456f2 | ||
![]() |
9f9244062a | ||
![]() |
e964f61d38 | ||
![]() |
badd52223a | ||
![]() |
90f7c531cd | ||
![]() |
26db4f3350 | ||
![]() |
cd669e22c1 | ||
![]() |
8ed65bfa17 | ||
![]() |
0737a362d8 | ||
![]() |
8167963212 | ||
![]() |
46830d2122 | ||
![]() |
9b9822cc3c | ||
![]() |
5ad5d16683 | ||
![]() |
9dfd49ca04 | ||
![]() |
4defeefe7e | ||
![]() |
5d0b5e69a5 | ||
![]() |
2ef597aed1 | ||
![]() |
bcba45fbd1 | ||
![]() |
2168a640af | ||
![]() |
8184555ee8 | ||
![]() |
5fa56387fd | ||
![]() |
62fde50442 | ||
![]() |
14d8ea582c | ||
![]() |
6351306f87 | ||
![]() |
1b5d435b86 | ||
![]() |
6242200905 | ||
![]() |
eb7477273f | ||
![]() |
b9417ca357 | ||
![]() |
a752cf4c97 | ||
![]() |
9d74cf5fc2 | ||
![]() |
fd1899f162 | ||
![]() |
9bd16e096f | ||
![]() |
0dea3249a5 | ||
![]() |
2c88561b44 | ||
![]() |
1bdae90fb0 | ||
![]() |
a72bb0c73b | ||
![]() |
7b6042d01f | ||
![]() |
ab09ae60f0 | ||
![]() |
9b289605c7 | ||
![]() |
c3ebf56ac1 | ||
![]() |
7c0689c056 | ||
![]() |
a6cb78380d | ||
![]() |
e58e18de33 | ||
![]() |
79839329b0 | ||
![]() |
682e88e0c5 | ||
![]() |
a8e9b824f3 | ||
![]() |
59e0e6bb65 | ||
![]() |
8cd650b07e | ||
![]() |
27057ea0c8 | ||
![]() |
db0e4cada6 | ||
![]() |
72ed3ce2d1 | ||
![]() |
3d344bdcdd | ||
![]() |
a76ee0acf2 | ||
![]() |
29f162c801 | ||
![]() |
5509cae91c | ||
![]() |
c203ac69ee | ||
![]() |
988a975bf1 | ||
![]() |
d1ed56926d | ||
![]() |
26568d5203 | ||
![]() |
b2ba6d9261 | ||
![]() |
69559ba242 | ||
![]() |
ba4e11a40a | ||
![]() |
02e44fc6b8 | ||
![]() |
7e1005dc62 | ||
![]() |
0dfd401537 | ||
![]() |
ec7c952270 | ||
![]() |
ec9d9d7d7e | ||
![]() |
0f6d0a44ea | ||
![]() |
d645f607ac | ||
![]() |
9877c6a3b0 | ||
![]() |
faf13489a1 | ||
![]() |
b4999993bf | ||
![]() |
3ad7ba66b5 | ||
![]() |
dcbe7294b7 | ||
![]() |
70d5c57334 | ||
![]() |
4050f55640 | ||
![]() |
2fb16e64e9 | ||
![]() |
792f702f9e | ||
![]() |
05f9ae6a89 | ||
![]() |
2b0d17e9ca | ||
![]() |
69396e6465 | ||
![]() |
d4a2e5c327 | ||
![]() |
11949b39ff | ||
![]() |
e74d880bac | ||
![]() |
875aab1e2c | ||
![]() |
df350fdd54 | ||
![]() |
0def714af2 | ||
![]() |
781dfdd7c9 | ||
![]() |
9ee60677f6 | ||
![]() |
956f4b198b | ||
![]() |
82ed5e9057 | ||
![]() |
c592cff1ee | ||
![]() |
b04d8849e7 | ||
![]() |
581b241f99 | ||
![]() |
24a2294512 | ||
![]() |
e4eb0e2596 | ||
![]() |
66d492b4b3 | ||
![]() |
b59bea16f0 | ||
![]() |
b92583d0df | ||
![]() |
2ceb6a8e53 | ||
![]() |
5b659ce8c9 | ||
![]() |
bb8f250f5f | ||
![]() |
5f1df5a87d | ||
![]() |
b0beeca0cb | ||
![]() |
f86d544916 | ||
![]() |
2a87a0fe28 | ||
![]() |
840e014f2b | ||
![]() |
a7b9398708 | ||
![]() |
cdd9452996 | ||
![]() |
96021e1a49 | ||
![]() |
96e0e8640d | ||
![]() |
cd31798870 | ||
![]() |
ee8229020b | ||
![]() |
722dd86810 | ||
![]() |
64080ef273 | ||
![]() |
82593f1d65 | ||
![]() |
42dd4d68e7 | ||
![]() |
2a69886556 | ||
![]() |
4511a0bd00 | ||
![]() |
7d05c40dc0 | ||
![]() |
88b8785cb8 | ||
![]() |
92deb0cc6a | ||
![]() |
98aff8f3b9 | ||
![]() |
dcbb156833 | ||
![]() |
7818574356 | ||
![]() |
75c0c4fff4 | ||
![]() |
03b5f08102 | ||
![]() |
ed63032a82 | ||
![]() |
fc4a39e9f3 | ||
![]() |
1b087c6eb3 | ||
![]() |
28a5d6bb38 | ||
![]() |
14069cd4fe | ||
![]() |
57c03ad045 | ||
![]() |
dc980b024e | ||
![]() |
0e07506716 | ||
![]() |
fed36ecdd8 | ||
![]() |
7b72a90bc6 | ||
![]() |
2e2c44f0af | ||
![]() |
0a6b54da36 | ||
![]() |
e29a38dfa4 | ||
![]() |
694ddf07a3 | ||
![]() |
ee94b7cbb2 | ||
![]() |
5928185599 | ||
![]() |
0c22469503 | ||
![]() |
a1cc44759b | ||
![]() |
da04f068f9 | ||
![]() |
6b8ae88db4 | ||
![]() |
487c2ed6bd | ||
![]() |
5633367397 | ||
![]() |
1d77556157 | ||
![]() |
574406dd5f | ||
![]() |
ac0e2e74d8 | ||
![]() |
1334a62aae | ||
![]() |
353ca79be3 | ||
![]() |
83c0b49da9 | ||
![]() |
4956bf367b | ||
![]() |
58e569864d | ||
![]() |
286ef83e8e | ||
![]() |
d056dbf9ee | ||
![]() |
c7817909ce | ||
![]() |
433ae3d0c7 | ||
![]() |
65e9dba82f | ||
![]() |
bebc543e3c | ||
![]() |
2f77a61b18 | ||
![]() |
49419350bb | ||
![]() |
082cf5d81f | ||
![]() |
aef81a6d83 | ||
![]() |
f3e331ecf7 | ||
![]() |
e29cc2578c | ||
![]() |
ed6ca006ce | ||
![]() |
593bc2de90 | ||
![]() |
edb8928d53 | ||
![]() |
8de2196b61 | ||
![]() |
34b80a36b4 | ||
![]() |
d39667bfb9 | ||
![]() |
0eb9ee8648 | ||
![]() |
854ab8910d | ||
![]() |
d0df1d29f5 | ||
![]() |
d1cd7e2be3 | ||
![]() |
85ff15a041 | ||
![]() |
7628cba990 | ||
![]() |
3106bfdd7b | ||
![]() |
6f0f63c286 | ||
![]() |
25ffd41ab9 | ||
![]() |
e2252a2840 | ||
![]() |
b30494ea8d | ||
![]() |
4c40d2d990 | ||
![]() |
1f15b6720f | ||
![]() |
b7521a9021 | ||
![]() |
6299143e4c | ||
![]() |
8ca1aa38a2 | ||
![]() |
a3250882df | ||
![]() |
5bb8231782 | ||
![]() |
821b6c1f28 | ||
![]() |
20d70927c9 | ||
![]() |
9aee0568bf | ||
![]() |
84a4bcd948 | ||
![]() |
e5d0aaf80d | ||
![]() |
083319fd24 | ||
![]() |
b1d79428a3 | ||
![]() |
931664e6b6 | ||
![]() |
b2b5445799 | ||
![]() |
c7432bbd98 | ||
![]() |
fe42cfe843 | ||
![]() |
f5bd90731d | ||
![]() |
c09a572925 | ||
![]() |
e54762be6a | ||
![]() |
5a758d8671 | ||
![]() |
94c386638f | ||
![]() |
101c32523d | ||
![]() |
15d466a045 | ||
![]() |
2eb3754953 | ||
![]() |
460f3471b5 | ||
![]() |
d3b7a435f9 | ||
![]() |
b3cf639ee2 | ||
![]() |
a7e102ffc7 | ||
![]() |
ae2745fdb7 | ||
![]() |
afbb8ba5a7 | ||
![]() |
52768a7ec9 | ||
![]() |
9db88a5c09 | ||
![]() |
2d93441188 | ||
![]() |
38493f9dd7 | ||
![]() |
6dced5ece0 | ||
![]() |
6593b6919e | ||
![]() |
4368c4a866 | ||
![]() |
5115e041e7 | ||
![]() |
c325911c0d | ||
![]() |
126d6017f2 | ||
![]() |
da10ab2e29 | ||
![]() |
ffe8d9ca6d | ||
![]() |
5c5dbf69ec | ||
![]() |
532248b55d | ||
![]() |
e56f29a510 | ||
![]() |
c3e696b942 | ||
![]() |
7aff0d3f1e | ||
![]() |
79a371f9b1 | ||
![]() |
7d23e5c474 | ||
![]() |
de335f4834 | ||
![]() |
d12ea48b97 | ||
![]() |
1540999f50 | ||
![]() |
d4f99ec899 | ||
![]() |
1c50612559 | ||
![]() |
b9d5c70301 | ||
![]() |
ab0fe5bdfa | ||
![]() |
0df8d9cace | ||
![]() |
e3217436c9 | ||
![]() |
d3e1cef8a2 | ||
![]() |
142dc498f8 | ||
![]() |
c987ea7841 | ||
![]() |
a5de69c65a | ||
![]() |
3426100baf | ||
![]() |
187bdaf75c | ||
![]() |
1248c38f3d | ||
![]() |
931d5242a1 | ||
![]() |
bee504facd | ||
![]() |
0ef134f20d | ||
![]() |
6d9ae8ed60 | ||
![]() |
3c2cea1201 | ||
![]() |
e9a0911bfc | ||
![]() |
4476eefd47 | ||
![]() |
179d536ccc | ||
![]() |
8d4602962b | ||
![]() |
a14fb9ec38 | ||
![]() |
48e90a4229 | ||
![]() |
fb360035ad | ||
![]() |
2a80761001 | ||
![]() |
dbf6748ddc | ||
![]() |
f23e8719ee | ||
![]() |
53785713c1 | ||
![]() |
633415dd3e | ||
![]() |
1a7ea0ce6a | ||
![]() |
08b627e86a | ||
![]() |
e90eceb285 | ||
![]() |
c3c09f5b76 | ||
![]() |
190df17adc | ||
![]() |
d239d641ff | ||
![]() |
6ced0a0fad | ||
![]() |
33c7b64f06 | ||
![]() |
76f30a0f20 | ||
![]() |
806b22ec85 | ||
![]() |
067629e38c | ||
![]() |
af51baa2d2 | ||
![]() |
0ab1dcaa6b | ||
![]() |
b50cc1a72c | ||
![]() |
0f0d240c04 | ||
![]() |
93f0db0196 | ||
![]() |
a05ddaeda1 | ||
![]() |
3642666e23 | ||
![]() |
57db11f10f | ||
![]() |
036a24884c | ||
![]() |
904a0d3e15 | ||
![]() |
02fa54ae89 | ||
![]() |
5a8a1e41e9 | ||
![]() |
f90e9bee31 | ||
![]() |
8521cc5c88 | ||
![]() |
4adf6951d9 | ||
![]() |
c69f81ec6f | ||
![]() |
c94e5ba430 | ||
![]() |
d6127cf797 | ||
![]() |
0f5748a24b | ||
![]() |
aa4ac8641a | ||
![]() |
e3f4344ae9 | ||
![]() |
d5fa9dc5dc | ||
![]() |
e7c6813ccb | ||
![]() |
38dc4beb44 | ||
![]() |
ae5edd17ef | ||
![]() |
cf7b849cdd | ||
![]() |
34554f0ced | ||
![]() |
7053d8fd7a | ||
![]() |
b492840512 | ||
![]() |
aee84a8167 | ||
![]() |
b8c6d7eb6a | ||
![]() |
5a563ef428 | ||
![]() |
d8cf2ae131 | ||
![]() |
1431472f07 | ||
![]() |
dfd60bd4cc | ||
![]() |
0b7affdc05 | ||
![]() |
0e5d54639a | ||
![]() |
888a4b1162 | ||
![]() |
f3e7f0d405 | ||
![]() |
4885dca04f | ||
![]() |
6dff0996bd | ||
![]() |
042d7a4a10 | ||
![]() |
3e0834f83c | ||
![]() |
cc4dba5179 | ||
![]() |
affdb57ecd | ||
![]() |
e5839b6980 | ||
![]() |
26dbd52373 | ||
![]() |
e4cbdd3747 | ||
![]() |
c3176f6b47 | ||
![]() |
7eaa942550 | ||
![]() |
929261b6f8 | ||
![]() |
608c5f944d | ||
![]() |
72f47733dc | ||
![]() |
f95f0dd9e5 | ||
![]() |
dc76634a6e | ||
![]() |
0089d471ae | ||
![]() |
3e697531fc | ||
![]() |
31e9eb3e34 | ||
![]() |
870bc0130d | ||
![]() |
eb11c23f10 | ||
![]() |
704fcca298 | ||
![]() |
ba08cf6c04 | ||
![]() |
ef4f6c429f | ||
![]() |
fa7a86141c | ||
![]() |
be1ebe89f1 | ||
![]() |
b573bf000f | ||
![]() |
e560adee4f | ||
![]() |
837368035a | ||
![]() |
9cc1d98cc0 | ||
![]() |
6a196672bb | ||
![]() |
0b640a0eb9 | ||
![]() |
902b66a71c | ||
![]() |
4a55e03d10 | ||
![]() |
14f07e63f1 | ||
![]() |
6f43176d35 | ||
![]() |
62055018fe | ||
![]() |
8563ef55a6 | ||
![]() |
bedae5768a | ||
![]() |
afcf23f29d | ||
![]() |
393bfa64ec | ||
![]() |
2b759c07c8 | ||
![]() |
f5a068b1b3 | ||
![]() |
9a26667c5d | ||
![]() |
f554f6d43b | ||
![]() |
0cfe430e27 | ||
![]() |
c429e6f48d | ||
![]() |
b54ee96233 | ||
![]() |
b47ef98197 | ||
![]() |
699b236ce5 | ||
![]() |
df79638fb6 | ||
![]() |
6b4584e91b | ||
![]() |
b041887402 | ||
![]() |
dfea195ec1 | ||
![]() |
60328a6baf | ||
![]() |
17a25a501e | ||
![]() |
a9b5a714e4 | ||
![]() |
4ce0d989fa | ||
![]() |
5a01171bbb | ||
![]() |
f44bcccd23 | ||
![]() |
fe5b429dda | ||
![]() |
4077fac39f | ||
![]() |
ea401cf5fe | ||
![]() |
925fa86271 | ||
![]() |
c611e51a2a | ||
![]() |
64ca3e52c6 | ||
![]() |
28abed9ab3 | ||
![]() |
95d7949655 | ||
![]() |
ba3f4281f1 | ||
![]() |
8658a26e2d | ||
![]() |
4b52a71c09 | ||
![]() |
54c1ba777c | ||
![]() |
72833a9bcd | ||
![]() |
6c2d65587b | ||
![]() |
bcfbecc40a | ||
![]() |
546fafbf37 | ||
![]() |
1c89e3efb0 | ||
![]() |
9251121ba0 | ||
![]() |
c93c229b0f | ||
![]() |
b78e7f57a0 | ||
![]() |
4a75f3dbd1 | ||
![]() |
0620b62023 | ||
![]() |
b4713e377a | ||
![]() |
af6ab5fc2c | ||
![]() |
93bd4dc3aa | ||
![]() |
65fa3cb624 | ||
![]() |
20274b1c65 | ||
![]() |
dce1b88694 | ||
![]() |
7a8bd92104 | ||
![]() |
cca5625df7 | ||
![]() |
0cedc7a418 | ||
![]() |
a0767f4664 | ||
![]() |
1266a3f160 | ||
![]() |
73c012c71a | ||
![]() |
ea45c4f42a | ||
![]() |
7abe2c1073 | ||
![]() |
2b35c044ad | ||
![]() |
ce38233de8 | ||
![]() |
3b56c78d5c | ||
![]() |
ddc1c5f373 | ||
![]() |
d88d287fc5 | ||
![]() |
c8b7de0879 | ||
![]() |
617aa89409 | ||
![]() |
886bc8033d | ||
![]() |
c91d8c8efa | ||
![]() |
3724bd5a10 | ||
![]() |
91c72f9ec9 | ||
![]() |
51e427e83c | ||
![]() |
9d14517202 | ||
![]() |
6ae896441a | ||
![]() |
8be67d02c4 | ||
![]() |
7d23beec5e | ||
![]() |
0a49b56566 | ||
![]() |
09b24cf1fd | ||
![]() |
4ec04240a5 | ||
![]() |
bf04962e90 | ||
![]() |
e1c0f5cf1e | ||
![]() |
c83d74b9f6 | ||
![]() |
533cf8deee | ||
![]() |
9877d5f517 | ||
![]() |
d57aad5612 | ||
![]() |
4a21249ee3 | ||
![]() |
6752adc939 | ||
![]() |
f4b0d134ca | ||
![]() |
bed0d3bd70 | ||
![]() |
3aeb026776 | ||
![]() |
96f04c1756 | ||
![]() |
622d938d9e | ||
![]() |
14183781dd | ||
![]() |
e3d8239b9f | ||
![]() |
94017189c6 | ||
![]() |
957c085e12 | ||
![]() |
1763a36a26 | ||
![]() |
ed29ab5137 | ||
![]() |
f7ca3a654f | ||
![]() |
1abcad1de5 | ||
![]() |
17e5ab611c | ||
![]() |
74906f3932 | ||
![]() |
8d30fffc2b | ||
![]() |
8944581c09 | ||
![]() |
62fc7739b5 | ||
![]() |
a4edb1d760 | ||
![]() |
17ef50cdf5 | ||
![]() |
caa340803f | ||
![]() |
27e8acbfe7 | ||
![]() |
19d0ddcdd9 | ||
![]() |
88137f01b2 | ||
![]() |
ae820a22f2 | ||
![]() |
ec11af53a1 | ||
![]() |
e529c79c4f | ||
![]() |
bf59570251 | ||
![]() |
a0744630ba | ||
![]() |
75b46e1a17 | ||
![]() |
0e98f1da55 | ||
![]() |
a455a89c58 | ||
![]() |
696eeee882 | ||
![]() |
8bcce9282e | ||
![]() |
fb780da327 | ||
![]() |
b058517912 | ||
![]() |
c9d815674a | ||
![]() |
3bafa7b80c | ||
![]() |
eaf65b6db2 | ||
![]() |
5a4e3baa51 | ||
![]() |
962d9118dd | ||
![]() |
1ecc36da57 | ||
![]() |
edb3d47a53 | ||
![]() |
ab9e6530b6 | ||
![]() |
2f4785cde8 | ||
![]() |
1f3255481f | ||
![]() |
5f70207076 | ||
![]() |
3ba3df7265 | ||
![]() |
f1080e1675 | ||
![]() |
06f6adc69c | ||
![]() |
33cb7947d6 | ||
![]() |
38929fed6e | ||
![]() |
c232fcc6dd | ||
![]() |
6227e40be3 | ||
![]() |
18e60445ed | ||
![]() |
d487fe5563 | ||
![]() |
cdb32685e4 | ||
![]() |
1fff0f1bd0 | ||
![]() |
cbc836a276 | ||
![]() |
be91e33828 | ||
![]() |
6430a25870 | ||
![]() |
12915f3e5a | ||
![]() |
c659e39db1 | ||
![]() |
44d53151f2 | ||
![]() |
7df2a0daba | ||
![]() |
30c933cdf3 | ||
![]() |
8f9303bc0f | ||
![]() |
ce10aa1fe2 | ||
![]() |
6d836bdb65 | ||
![]() |
7b7b1f2647 | ||
![]() |
a5c36bbb20 | ||
![]() |
c55133dc8b | ||
![]() |
11fe9ec744 | ||
![]() |
a1cdbad187 | ||
![]() |
09af1aa156 | ||
![]() |
f12d81259f | ||
![]() |
8432dc6286 | ||
![]() |
af278d8fea | ||
![]() |
d7135db5ad | ||
![]() |
58473f0ff9 | ||
![]() |
1cce1b2713 | ||
![]() |
9dbb8171a6 | ||
![]() |
31b9249cc8 | ||
![]() |
cac8ea6388 | ||
![]() |
441b43bef6 | ||
![]() |
c1d67153ce | ||
![]() |
c85ae85002 | ||
![]() |
52835b2ce2 | ||
![]() |
fd1846eecf | ||
![]() |
6a6ddf6e1f | ||
![]() |
623d171d79 | ||
![]() |
1688f99096 | ||
![]() |
1cc62c40a0 | ||
![]() |
296f96cf17 | ||
![]() |
5536b951cf | ||
![]() |
1b5bfec27f | ||
![]() |
8fe9e4d245 | ||
![]() |
f1f60b9ad4 | ||
![]() |
10f1c675d0 | ||
![]() |
3a6caeb35d | ||
![]() |
053916f2ca | ||
![]() |
13bafaad4c | ||
![]() |
816ad304df | ||
![]() |
dca8bcd7c6 | ||
![]() |
b110d83456 | ||
![]() |
6760fe2437 | ||
![]() |
2e8b647a51 | ||
![]() |
bd3b7f9e73 | ||
![]() |
5855820569 | ||
![]() |
28ff3216ef | ||
![]() |
625901482a | ||
![]() |
471812d789 | ||
![]() |
62ad86e88d | ||
![]() |
da26c9a677 | ||
![]() |
ea171225d8 | ||
![]() |
6e164313ce | ||
![]() |
7fa50e5c5e | ||
![]() |
f0b426ae89 | ||
![]() |
06a043764d | ||
![]() |
5e47faa606 | ||
![]() |
74d93fc682 | ||
![]() |
1f9c02cc1e | ||
![]() |
66342644a6 | ||
![]() |
42d1db64db | ||
![]() |
1c555672f8 | ||
![]() |
78fe1cbab1 | ||
![]() |
cb916d4861 | ||
![]() |
fcb5c8f8da | ||
![]() |
49b5d0e694 | ||
![]() |
80959aa0ca | ||
![]() |
54d5907f14 | ||
![]() |
b2c4ea13f6 | ||
![]() |
159f03e7ca | ||
![]() |
36396b7583 | ||
![]() |
f4b2255bc3 | ||
![]() |
c46b4284b1 | ||
![]() |
431e04c35c | ||
![]() |
17d19e9584 | ||
![]() |
6eb4244f32 | ||
![]() |
6c2e39b2d3 | ||
![]() |
7a0fd64cf9 | ||
![]() |
dfdc6c9497 | ||
![]() |
f160ec767d | ||
![]() |
3f5a1b9587 | ||
![]() |
20c424c77f | ||
![]() |
e04515d8e2 | ||
![]() |
f7b12924db | ||
![]() |
b6cef34a3b | ||
![]() |
7131efa07f | ||
![]() |
9410701722 | ||
![]() |
24f70b0d1e | ||
![]() |
862c4b8faf | ||
![]() |
bb60b01ef2 | ||
![]() |
62677209a2 | ||
![]() |
00f527ea5e | ||
![]() |
6290a71194 | ||
![]() |
a445d96702 | ||
![]() |
27ef3cf11d | ||
![]() |
fb493cfd73 | ||
![]() |
2c24ed6495 | ||
![]() |
39e5e3f19b | ||
![]() |
0ac555c4e2 | ||
![]() |
a11ff844b3 | ||
![]() |
51d83e18cc | ||
![]() |
0cb87ba6df | ||
![]() |
4204789d4b | ||
![]() |
7fed80a304 | ||
![]() |
01868a41ca | ||
![]() |
88f27ad520 | ||
![]() |
dc7584ae7f | ||
![]() |
448c9b39f4 | ||
![]() |
a7d79d12cc | ||
![]() |
287a54474f | ||
![]() |
cc59ea1486 | ||
![]() |
40b544fa3b | ||
![]() |
ec9a02e8b8 | ||
![]() |
6535345c1c | ||
![]() |
92a418c8a8 | ||
![]() |
dcdb16676d | ||
![]() |
eeb8cabf49 | ||
![]() |
1bdce9fe96 | ||
![]() |
a0b377104f | ||
![]() |
23473af773 | ||
![]() |
3350184b19 | ||
![]() |
4ba1e70636 | ||
![]() |
a4965d37ae | ||
![]() |
af99182016 | ||
![]() |
a90261ed19 | ||
![]() |
67380f6876 | ||
![]() |
776edf84af | ||
![]() |
b836495e6e | ||
![]() |
a25bc9aac8 | ||
![]() |
f8a2b9afd8 | ||
![]() |
a4927c7013 | ||
![]() |
69734143b1 | ||
![]() |
328f369777 | ||
![]() |
686e24addd | ||
![]() |
2e06fa41ab | ||
![]() |
cfa9e04377 | ||
![]() |
a12a46c635 | ||
![]() |
ac5866dc0f | ||
![]() |
8e10d5cd9f | ||
![]() |
53f5c1006b | ||
![]() |
60c55f7ca2 | ||
![]() |
d717860dda | ||
![]() |
3f3bd52c21 | ||
![]() |
a857295244 | ||
![]() |
78e232f6eb | ||
![]() |
65fa715830 | ||
![]() |
71315146db | ||
![]() |
e4a3ef2689 | ||
![]() |
05bb118cd8 | ||
![]() |
4182234be6 | ||
![]() |
9bc17f50c0 | ||
![]() |
6270370fc0 | ||
![]() |
4a2091c941 | ||
![]() |
0a25ea5df1 | ||
![]() |
60ec4c02ee | ||
![]() |
4832d107f4 | ||
![]() |
a4c3605dbd | ||
![]() |
0483880f2a | ||
![]() |
39ee0a92a8 | ||
![]() |
b327ffb108 | ||
![]() |
7803a48237 | ||
![]() |
42b3e111f8 | ||
![]() |
6bc1d32a88 | ||
![]() |
60ede5f92b | ||
![]() |
a1896b43d0 | ||
![]() |
8ce2192e5c | ||
![]() |
9b6ccd8488 | ||
![]() |
2cbfcf2fe8 | ||
![]() |
f3781e8d0d | ||
![]() |
4f96c10430 | ||
![]() |
c6bf9b6799 | ||
![]() |
60a5847ae6 | ||
![]() |
2ebcbc4cea | ||
![]() |
1ce0972b88 | ||
![]() |
10d0660972 | ||
![]() |
bd48ca44ee | ||
![]() |
1e5a4ef402 | ||
![]() |
bdd70984e6 | ||
![]() |
f5dc76a98f | ||
![]() |
b78b657377 | ||
![]() |
7617439915 | ||
![]() |
3d9da8b4e3 | ||
![]() |
d85867a245 | ||
![]() |
a5b7e5faf0 | ||
![]() |
0751f5e317 | ||
![]() |
d7eaa38df7 | ||
![]() |
669e3706da | ||
![]() |
0d26bae037 | ||
![]() |
9080441b87 | ||
![]() |
0c54f2dcd4 | ||
![]() |
0e43504e18 | ||
![]() |
d68d150d3f | ||
![]() |
ee46d0970b | ||
![]() |
b8f3493138 | ||
![]() |
9bad8c9eb8 | ||
![]() |
576e2c6a1f | ||
![]() |
a435d41eb2 | ||
![]() |
f533151adb | ||
![]() |
ac84942917 | ||
![]() |
a774817240 | ||
![]() |
1bb38c3917 | ||
![]() |
9f959ce77c | ||
![]() |
025c1ae204 | ||
![]() |
0104362b3d | ||
![]() |
1956692484 | ||
![]() |
24d7b5b851 | ||
![]() |
1d82bb0987 | ||
![]() |
3ccb525260 | ||
![]() |
312f7fbe77 | ||
![]() |
ad90c11ab0 | ||
![]() |
84d94b05bc | ||
![]() |
013aac4543 | ||
![]() |
59561abdc2 | ||
![]() |
c809d2daba | ||
![]() |
3db28f43b4 | ||
![]() |
b5415f442a | ||
![]() |
e7acb9ed5c | ||
![]() |
6902060cdd | ||
![]() |
a4a7f1a74f | ||
![]() |
3d6d2444be | ||
![]() |
dc96cb38ce | ||
![]() |
c343ccc293 | ||
![]() |
1dfec05eec | ||
![]() |
710f172dee | ||
![]() |
d495709c99 | ||
![]() |
947c14353e | ||
![]() |
f79223cd41 | ||
![]() |
e7f3f4eae4 | ||
![]() |
d0aaa971fe | ||
![]() |
a06cd0da84 | ||
![]() |
8a6ba3b35f | ||
![]() |
0b58155d43 | ||
![]() |
af4d56fd41 | ||
![]() |
e158dd0cec | ||
![]() |
db12f6c649 | ||
![]() |
78b3273e44 | ||
![]() |
ceaa71bf1b | ||
![]() |
b49e5aa50d | ||
![]() |
c4a60aefce | ||
![]() |
8f303a326f | ||
![]() |
b26dfdb7c0 | ||
![]() |
84d08cc762 | ||
![]() |
8b9bd9cbb6 | ||
![]() |
aada9a7dbc | ||
![]() |
c6a5d5f7b1 | ||
![]() |
bd126751e9 | ||
![]() |
d674b61275 | ||
![]() |
461daf0271 | ||
![]() |
2d517ca0cb | ||
![]() |
00d8fd2e16 | ||
![]() |
4cadfa9375 | ||
![]() |
90c1200a08 | ||
![]() |
359fcee98c | ||
![]() |
fda5393905 | ||
![]() |
6942964187 | ||
![]() |
b0db5e7d82 | ||
![]() |
4dc26af23d | ||
![]() |
9465d92fa0 | ||
![]() |
3282370f74 | ||
![]() |
65cad07e3a | ||
![]() |
166710f041 | ||
![]() |
8ba3eb862d | ||
![]() |
a10bc5b8d8 | ||
![]() |
1f2d53114d | ||
![]() |
1fad95f6e3 | ||
![]() |
bd18f19821 | ||
![]() |
5b0e22c1b6 | ||
![]() |
261aaf191c | ||
![]() |
6cc2a185d0 | ||
![]() |
42d284f8d8 | ||
![]() |
7c25e1cc8a | ||
![]() |
3925f74395 | ||
![]() |
3386dac78e | ||
![]() |
ee5c417ac3 | ||
![]() |
bc8a04e544 | ||
![]() |
3ed8b0fda2 | ||
![]() |
69995bea1c | ||
![]() |
067e9ac53e | ||
![]() |
1b8ec28b3f | ||
![]() |
83716656cf | ||
![]() |
5b6454706a | ||
![]() |
5cd90f93b9 | ||
![]() |
1223cf2629 | ||
![]() |
00d0d38b54 | ||
![]() |
a254e1e2f9 | ||
![]() |
8cd3b9ad12 | ||
![]() |
ef82079162 | ||
![]() |
fa3eefa423 | ||
![]() |
8b92492745 | ||
![]() |
ac26edb719 | ||
![]() |
f7ef291dd8 | ||
![]() |
e89fdcfd1a | ||
![]() |
f50cf5b487 | ||
![]() |
e82833f299 | ||
![]() |
cf6c0c0868 | ||
![]() |
1e25fe2b18 | ||
![]() |
9a0ca2807f | ||
![]() |
4f6f48e379 | ||
![]() |
597551cdf3 | ||
![]() |
e890cb4ad0 | ||
![]() |
a2708731a8 | ||
![]() |
67ffc41edb | ||
![]() |
472da6b8b1 | ||
![]() |
a8330ef2e1 | ||
![]() |
3b6bf27a98 | ||
![]() |
3c6803bb3f | ||
![]() |
be56ad4477 | ||
![]() |
76d0f31b4b | ||
![]() |
500d3169a3 | ||
![]() |
ef1cc9408d | ||
![]() |
39a77945d1 | ||
![]() |
c1868817e5 | ||
![]() |
b3c27d1fca | ||
![]() |
e659e3c56f | ||
![]() |
54048cbfc3 | ||
![]() |
8cdb5c4187 | ||
![]() |
72b7238b96 | ||
![]() |
ff1446982f | ||
![]() |
e795e23e42 | ||
![]() |
36c5e02f18 | ||
![]() |
5e96913ba3 | ||
![]() |
2211505d71 | ||
![]() |
fb9c0e44be | ||
![]() |
c201624f99 | ||
![]() |
e086b520e7 | ||
![]() |
46b00bafdf | ||
![]() |
512446dcab | ||
![]() |
69739b4572 | ||
![]() |
9eee573ce9 | ||
![]() |
8a44b6f2e5 | ||
![]() |
932396f879 | ||
![]() |
382f4adb2f | ||
![]() |
4b21cc8299 | ||
![]() |
f623768081 | ||
![]() |
6e6cf9923d | ||
![]() |
3906ce05fc | ||
![]() |
9d078c8487 | ||
![]() |
745a02f0ee | ||
![]() |
178b4eaf32 | ||
![]() |
148f048723 | ||
![]() |
e6761a6f8e | ||
![]() |
bc89171463 | ||
![]() |
1d4847ab0a | ||
![]() |
53aac9044b | ||
![]() |
6b6907af3f | ||
![]() |
0b79a1181c | ||
![]() |
b3ac5ca3bb | ||
![]() |
b5144dfa26 | ||
![]() |
361513b7a2 | ||
![]() |
dcc8ba5a54 | ||
![]() |
3b4306b7ab | ||
![]() |
5ffed01a37 | ||
![]() |
83792bdca2 | ||
![]() |
861247d430 | ||
![]() |
43557e40df | ||
![]() |
c83410bac2 | ||
![]() |
88d7ce55a5 | ||
![]() |
cb4bd25df1 | ||
![]() |
91d5d1003b | ||
![]() |
618c6da0eb | ||
![]() |
f38a2e6258 | ||
![]() |
abf4a5763a | ||
![]() |
8a72f62d14 | ||
![]() |
933b8d58e7 | ||
![]() |
0ebac05a4b | ||
![]() |
0ca97b495f | ||
![]() |
4ef7429aa8 | ||
![]() |
ff35e06a66 | ||
![]() |
4df917e65e | ||
![]() |
3e498a4827 | ||
![]() |
25e6b236b8 | ||
![]() |
edb6f3cd1c | ||
![]() |
6d4c6b1738 | ||
![]() |
0653dab6ee | ||
![]() |
677f3dcf29 | ||
![]() |
756b91007e | ||
![]() |
2a7381a677 | ||
![]() |
9a1f90acc0 | ||
![]() |
139d4dc033 | ||
![]() |
c77b0e198b | ||
![]() |
7eea968bcf | ||
![]() |
09fce4e8bc | ||
![]() |
36cebe480c | ||
![]() |
8f258e709a | ||
![]() |
2734454717 | ||
![]() |
dbb81de763 | ||
![]() |
9b3ef2ffa2 | ||
![]() |
56a99c4d29 | ||
![]() |
b12fcff25a | ||
![]() |
8f64f5452d | ||
![]() |
1191bf232d | ||
![]() |
7371cccba6 | ||
![]() |
9aedf0f36b | ||
![]() |
1694b764e0 | ||
![]() |
e88faa64fe | ||
![]() |
0075170432 | ||
![]() |
29942ff81b | ||
![]() |
205acf1dc0 | ||
![]() |
2e6a4d08e6 | ||
![]() |
3f37ad7c8e | ||
![]() |
6fadc98303 | ||
![]() |
887de51d89 | ||
![]() |
8a688b84cb | ||
![]() |
3081aa7b58 | ||
![]() |
9bf00e3d21 | ||
![]() |
e86fd91646 | ||
![]() |
bd677e8510 | ||
![]() |
0fd1ee7209 | ||
![]() |
7747cb7aa0 | ||
![]() |
2b1d13ab5b | ||
![]() |
55e4d9f9d0 | ||
![]() |
9ba46e3060 | ||
![]() |
cf1a8eff2a | ||
![]() |
0531f19538 | ||
![]() |
986a20ecca | ||
![]() |
f1c0696ff9 | ||
![]() |
623a907004 | ||
![]() |
9dbf2103ff | ||
![]() |
b05bf0b693 | ||
![]() |
ddcaed11e2 | ||
![]() |
d986a92702 | ||
![]() |
4b9792c34a | ||
![]() |
08575e3d09 | ||
![]() |
a3b64d3ebe | ||
![]() |
91048f9b15 | ||
![]() |
1a3556d39e | ||
![]() |
74d56792c6 | ||
![]() |
d5ff927c72 | ||
![]() |
427954150a | ||
![]() |
16064f68e8 | ||
![]() |
5866b0fcd6 | ||
![]() |
2763155676 | ||
![]() |
8c7adde890 | ||
![]() |
192acc169e | ||
![]() |
56ed536130 | ||
![]() |
d9addcda8e | ||
![]() |
cae9993429 | ||
![]() |
daa62c73f7 | ||
![]() |
531fae64f9 | ||
![]() |
64226a7344 | ||
![]() |
c68f894f5f | ||
![]() |
6b3ddcb741 | ||
![]() |
b137cc96d3 | ||
![]() |
f31e736181 | ||
![]() |
db2ba1ad7a | ||
![]() |
c4c5cc3d2e | ||
![]() |
7071cdbfcf | ||
![]() |
f3cca25ecf | ||
![]() |
d841b06882 | ||
![]() |
b2f20d458d | ||
![]() |
0fce2c6347 | ||
![]() |
2ab1fba3d6 | ||
![]() |
47ab4c588d | ||
![]() |
1263a0cfcf | ||
![]() |
97dcd8b6e2 | ||
![]() |
7ae453b81d | ||
![]() |
8097fb0769 | ||
![]() |
747efc6ee6 | ||
![]() |
663b08f428 | ||
![]() |
e206f16723 | ||
![]() |
b179d2a945 | ||
![]() |
3b24018bba | ||
![]() |
0ae0e196fd | ||
![]() |
a550d21b9a | ||
![]() |
c439a526dd | ||
![]() |
c3bf5119eb | ||
![]() |
24c9270bed | ||
![]() |
4240433e3d | ||
![]() |
cdcc0d314d | ||
![]() |
d87cf5f58b | ||
![]() |
f3a0f78fb9 | ||
![]() |
55852bd15b | ||
![]() |
a1d423090c | ||
![]() |
307a8e21df | ||
![]() |
aba1ba9325 | ||
![]() |
585de8c1de | ||
![]() |
8d77b6900a | ||
![]() |
a23ce61446 | ||
![]() |
e48b67cd47 | ||
![]() |
2818ed5c9d | ||
![]() |
d6687603d1 | ||
![]() |
0476bf7cee | ||
![]() |
9edcf537f8 | ||
![]() |
4a291d5f20 | ||
![]() |
e21755322f | ||
![]() |
ff369c7400 | ||
![]() |
053242e197 | ||
![]() |
3b4fab5aae | ||
![]() |
08f913e976 | ||
![]() |
92bc611c5e | ||
![]() |
615d5ce901 | ||
![]() |
816707c643 | ||
![]() |
cb58166244 | ||
![]() |
b68e98f519 | ||
![]() |
58a0b7776c | ||
![]() |
e099b9cd2b | ||
![]() |
b0bcb2a85c | ||
![]() |
02370c331a | ||
![]() |
74ee2aff33 | ||
![]() |
68b440920c | ||
![]() |
1271a09e00 | ||
![]() |
7d9f9019c2 | ||
![]() |
e86710f666 | ||
![]() |
0e10ddfa54 | ||
![]() |
68e9dfe9b3 | ||
![]() |
92e667d24e | ||
![]() |
1772d5751f | ||
![]() |
5d099fb2e4 | ||
![]() |
852dce34ce | ||
![]() |
d0c3577c09 | ||
![]() |
9254fb3f87 | ||
![]() |
c6a2430767 | ||
![]() |
f34afaf586 | ||
![]() |
c8b7c9b5dc | ||
![]() |
0b3f3c9e14 | ||
![]() |
c8ccdc715b | ||
![]() |
ebb00cdcb6 | ||
![]() |
42294b027a | ||
![]() |
708995d542 | ||
![]() |
4d130af609 | ||
![]() |
9db99a07d0 | ||
![]() |
c898716b06 | ||
![]() |
2a221d9cfb | ||
![]() |
a14ea6c13d | ||
![]() |
ec13b50146 | ||
![]() |
bc9e451d6b | ||
![]() |
62ea78dfbf | ||
![]() |
0126587d6f | ||
![]() |
ff57527936 | ||
![]() |
4453049e08 | ||
![]() |
9129c4d2b1 | ||
![]() |
ff4e5df44c | ||
![]() |
3702e29135 | ||
![]() |
89bcfecfb5 | ||
![]() |
68d10f10c4 | ||
![]() |
07f70af96d | ||
![]() |
acc939c581 | ||
![]() |
c51a9a4c28 | ||
![]() |
e2bba4ac94 | ||
![]() |
42257d9615 | ||
![]() |
da2e371dfd | ||
![]() |
7e24059900 | ||
![]() |
a985c19ad8 | ||
![]() |
ddc3555015 | ||
![]() |
71f12e7a6a | ||
![]() |
aa2f900468 | ||
![]() |
05af783bf4 | ||
![]() |
c34ff50345 | ||
![]() |
3b4603fb5d | ||
![]() |
ae714121b8 | ||
![]() |
46d6f62a73 | ||
![]() |
bce6a6621c | ||
![]() |
2f05e3f8d9 | ||
![]() |
e0b8d88ca6 | ||
![]() |
03f1d3e958 | ||
![]() |
bc1334dd6d | ||
![]() |
f07a142274 | ||
![]() |
6a05c57dcf | ||
![]() |
a7082d572a | ||
![]() |
f896f65095 | ||
![]() |
4321668806 | ||
![]() |
a717ef2baf | ||
![]() |
bea7fd14b7 | ||
![]() |
744d1675e5 | ||
![]() |
580d7eea60 | ||
![]() |
f2b616dddb | ||
![]() |
69ef66b0f2 | ||
![]() |
845a5cc317 | ||
![]() |
b7f9d96b28 | ||
![]() |
7f71440039 | ||
![]() |
7767dfbd4d | ||
![]() |
647086c8cb | ||
![]() |
038856a1f7 | ||
![]() |
372fc3d810 | ||
![]() |
8f200d6488 | ||
![]() |
b3d0172918 | ||
![]() |
2119e2012a | ||
![]() |
d7d2b31e8e | ||
![]() |
5953b30d45 | ||
![]() |
41102b3bb8 | ||
![]() |
56d5f68e8c | ||
![]() |
71d6fc5a4a | ||
![]() |
063b239b5d | ||
![]() |
b4bb93c81e | ||
![]() |
2b75076f82 | ||
![]() |
dedbf14f97 | ||
![]() |
434c73f507 | ||
![]() |
29697d5ae5 | ||
![]() |
b6289557af | ||
![]() |
8dfa13dd06 | ||
![]() |
74df7a91b1 | ||
![]() |
b20aa1911c | ||
![]() |
6b7f50aed8 | ||
![]() |
cee3e6744b | ||
![]() |
105ee469e8 | ||
![]() |
f3bacad233 | ||
![]() |
6b4c5d0427 | ||
![]() |
b3b3acdb1e | ||
![]() |
e3c7b83ae0 | ||
![]() |
b05efd3d36 | ||
![]() |
640d227ea5 | ||
![]() |
8d7e5b0c9d | ||
![]() |
46d9b656f9 | ||
![]() |
a28d431817 | ||
![]() |
9224b4c316 | ||
![]() |
20ada95312 | ||
![]() |
4d60447c3d | ||
![]() |
5bfe29b498 | ||
![]() |
09160b1a53 | ||
![]() |
3f36c049f9 | ||
![]() |
76d8ec1dc9 | ||
![]() |
eec39e008d | ||
![]() |
066baa3745 | ||
![]() |
94db62baa5 | ||
![]() |
211affa79d | ||
![]() |
5accf5c56c | ||
![]() |
31551ac1dc | ||
![]() |
9b0c002684 | ||
![]() |
b34b236c7f | ||
![]() |
1e2387ed00 | ||
![]() |
66a3b97dd0 | ||
![]() |
9e98e8f7dd | ||
![]() |
0ab8480149 | ||
![]() |
969790a0a0 | ||
![]() |
e1b946fc38 | ||
![]() |
af63ae6ba8 |
6
.dockerignore
Normal file
@ -0,0 +1,6 @@
|
||||
build
|
||||
dist
|
||||
.dart_tool
|
||||
.idea
|
||||
.github
|
||||
.git
|
12
.env.example
Normal file
@ -0,0 +1,12 @@
|
||||
# 0 or 1
|
||||
# 0 = disable
|
||||
# 1 = enable
|
||||
ENABLE_UPDATE_CHECK=$ENABLE_UPDATE_CHECK
|
||||
|
||||
LASTFM_API_KEY=$LASTFM_API_KEY
|
||||
LASTFM_API_SECRET=$LASTFM_API_SECRET
|
||||
|
||||
# Release channel. Can be: nightly, stable
|
||||
RELEASE_CHANNEL=$RELEASE_CHANNEL
|
||||
|
||||
HIDE_DONATIONS=$HIDE_DONATIONS
|
3
.fvm/fvm_config.json
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"flutterSdkVersion": "3.35.2"
|
||||
}
|
25
.github/Dockerfile
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
ARG FLUTTER_VERSION
|
||||
|
||||
FROM --platform=linux/arm64 krtirtho/flutter_distributor:${FLUTTER_VERSION}
|
||||
|
||||
ARG BUILD_VERSION
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY . .
|
||||
|
||||
RUN chown -R $(whoami) /app
|
||||
|
||||
RUN rustup target add aarch64-unknown-linux-gnu
|
||||
|
||||
RUN flutter pub get
|
||||
|
||||
RUN alias dpkg-deb="dpkg-deb --Zxz" &&\
|
||||
flutter_distributor package --platform=linux --targets=deb --skip-clean
|
||||
|
||||
RUN make tar VERSION=${BUILD_VERSION} ARCH=arm64 PKG_ARCH=aarch64
|
||||
|
||||
RUN mv build/spotube-linux-*-aarch64.tar.xz dist/ &&\
|
||||
mv dist/**/spotube-*-linux.deb dist/Spotube-linux-aarch64.deb
|
||||
|
||||
CMD [ "sleep", "5000000" ]
|
4
.github/FUNDING.yml
vendored
@ -1,2 +1,4 @@
|
||||
open_collective: spotube
|
||||
ko_fi: krtirtho
|
||||
patreon: krtirtho
|
||||
custom:
|
||||
- "https://www.buymeacoffee.com/krtirtho"
|
||||
|
41
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@ -1,41 +0,0 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
title: ''
|
||||
labels: bug
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**To Reproduce**
|
||||
Steps to reproduce the behavior:
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. Scroll down to '....'
|
||||
4. See error
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Screenshots**
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
|
||||
**Installation Source/Method**
|
||||
- Package Manager: <e.g flatpak/chocolatey>
|
||||
- Community Repo: <e.g AUR/appimagehub>
|
||||
- Binary Source: <resource_url>
|
||||
|
||||
**Desktop (please complete the following information):**
|
||||
- OS: [e.g. archlinux]
|
||||
- Version [e.g. v1.0.0]
|
||||
|
||||
**Smartphone (please complete the following information):**
|
||||
- Device: [e.g. iPhone6]
|
||||
- OS: [e.g. iOS8.1]
|
||||
- Version [e.g. v1.0.0]
|
||||
|
||||
**Additional context**
|
||||
Add any other context about the problem here.
|
106
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
Normal file
@ -0,0 +1,106 @@
|
||||
name: 🐛 Bug
|
||||
description: Report a bug or an incorrect behavior
|
||||
title: "Write the title here"
|
||||
labels:
|
||||
- bug
|
||||
|
||||
body:
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Is there an existing issue for this? (Please read the description)
|
||||
description: |
|
||||
🚨 PLEASE! Make sure to check if this issue is a duplicate. 🚨
|
||||
|
||||
Don't waste our time, we are working hard to make Spotube better for you.
|
||||
|
||||
Try with multiple similar keywords, and check the closed issues too.
|
||||
options:
|
||||
- label: I have searched the existing issues
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Current Behavior
|
||||
description: Write what you are experiencing currently.
|
||||
placeholder: |
|
||||
The app isn't working as expected. It crashes when I do this...
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Expected Behavior
|
||||
description: Write what you expected to happen.
|
||||
placeholder: |
|
||||
The app should do this when I do that...
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Steps to reproduce
|
||||
description: Steps to reproduce the issue. A not well written description might lead to the delay in fixing the issue.
|
||||
placeholder: |
|
||||
1. I opened the app
|
||||
2. I did this
|
||||
3. And that
|
||||
4. Then this happened
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Logs
|
||||
description: |
|
||||
If you have any logs, paste them here. Make sure to remove any sensitive information.
|
||||
You can find the logs in the app's Settings > Developers > Logs page.
|
||||
value: |
|
||||
<details>
|
||||
<summary>Logs</summary>
|
||||
|
||||
```
|
||||
<Replace this line by pasting your logs here>
|
||||
```
|
||||
</details>
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
attributes:
|
||||
label: Operating System
|
||||
description: The OS in which you used Spotube to face the issue. Use comma to separate multiple OS.
|
||||
placeholder: Android, Linux, macOS or Windows? Make sure to include the version too.
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
attributes:
|
||||
label: Spotube version
|
||||
description: In which version of Spotube did you encounter this bug?
|
||||
placeholder: (e.g.) v3.0.0
|
||||
- type: dropdown
|
||||
attributes:
|
||||
label: Installation source
|
||||
description: Where did you install Spotube from?
|
||||
multiple: true
|
||||
options:
|
||||
- "Website (spotube.krtirtho.dev)"
|
||||
- "GitHub Releases (Binary)"
|
||||
- "GitHub Actions (Nightly Binary)"
|
||||
- "Play Store (Android)"
|
||||
- "F-Droid (Android)"
|
||||
- "Arch User Repository (AUR)"
|
||||
- "Flathub (Flatpak)"
|
||||
- "chocolatey (Windows)"
|
||||
- "WinGet (Windows)"
|
||||
- "Scoop (Windows)"
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Additional information
|
||||
description: Anything else you'd like to include?
|
||||
validations:
|
||||
required: false
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Self grab
|
||||
description: |
|
||||
If you are a developer and want to work on this issue yourself, you can check this box and wait for maintainer response. Any contributions are welcome!
|
||||
|
||||
This project is maintained by one person. So PRs are always welcome. This is the best way to get your issue fixed faster.
|
||||
options:
|
||||
- label: I'm ready to work on this issue!
|
||||
required: false
|
5
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: Ask a question
|
||||
url: https://github.com/KRTirtho/spotube/discussions/new?category=q-a
|
||||
about: The place for questions, support and feature requests
|
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
@ -1,20 +0,0 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
title: ''
|
||||
labels: enhancement
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
||||
**Describe the solution you'd like**
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
**Additional context**
|
||||
Add any other context or screenshots about the feature request here.
|
45
.github/ISSUE_TEMPLATE/new_feature.yml
vendored
Normal file
@ -0,0 +1,45 @@
|
||||
name: ✨ New Feature
|
||||
description: Suggest an idea
|
||||
title: "Write the title here"
|
||||
labels:
|
||||
- enhancement
|
||||
|
||||
body:
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Is there an existing issue for this?
|
||||
description: Make sure to check if this issue is a duplicate.
|
||||
options:
|
||||
- label: I have searched the existing issues
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Pain
|
||||
description: Explain the pain you're experiencing.
|
||||
placeholder: I don't like that I've to do this / I'd like to have that
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Suggested solution
|
||||
description: Tell us about a solution you can think of
|
||||
placeholder: You could add that / change this / use that
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Useful resources
|
||||
description: Provide us with some useful resource which could help us implement your suggestion.
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Additional information
|
||||
description: Anything else you'd like to include?
|
||||
validations:
|
||||
required: false
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Self grab
|
||||
description: If you are a developer and want to work on this issue yourself, you can check this box and wait for maintainer response. We welcome contributions!
|
||||
options:
|
||||
- label: I'm ready to work on this issue!
|
||||
required: false
|
16
.github/dependabot.yml
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
version: 2
|
||||
|
||||
enable-beta-ecosystems: true
|
||||
|
||||
updates:
|
||||
- package-ecosystem: "pub"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
target-branch: "dev"
|
||||
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
target-branch: "dev"
|
83
.github/workflows/flutter-build.yml
vendored
@ -1,83 +0,0 @@
|
||||
name: Flutter Cross Build
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- build
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build_ubuntu:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: subosito/flutter-action@v2.2.0
|
||||
with:
|
||||
cache: true
|
||||
- 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: flutter config --enable-linux-desktop
|
||||
- run: flutter pub get
|
||||
- run: dart bin/create-secrets.dart '${{ secrets.LYRICS_SECRET }}' '${{ secrets.SPOTIFY_SECRET }}'
|
||||
- run: flutter clean
|
||||
- run: flutter build linux
|
||||
- run: make deb
|
||||
- run: make tar
|
||||
- run: wget https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage -O /usr/local/bin/appimagetool
|
||||
- run: chmod +x /usr/local/bin/appimagetool
|
||||
- run: pip3 install appimage-builder
|
||||
- run: make appimage
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: Spotube-Linux-Bundle
|
||||
path: |
|
||||
build/Spotube-linux-x86_64.deb
|
||||
build/Spotube-linux-x86_64.tar.xz
|
||||
build/Spotube-*-x86_64.AppImage
|
||||
# Building Android Application
|
||||
- run: flutter build apk
|
||||
- run: make apk
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: Spotube-Android-Bundle
|
||||
path: |
|
||||
build/Spotube-android-all-arch.apk
|
||||
build_windows:
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: subosito/flutter-action@v2.2.0
|
||||
with:
|
||||
cache: true
|
||||
- run: flutter config --enable-windows-desktop
|
||||
- run: flutter pub get
|
||||
- run: dart bin/create-secrets.dart '${{ secrets.LYRICS_SECRET }}' '${{ secrets.SPOTIFY_SECRET }}'
|
||||
- run: flutter build windows
|
||||
- run: ls build/windows/runner/Release
|
||||
- run: choco install make -y
|
||||
- run: make innoinstall
|
||||
- run: make inno
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: Spotube-Windows-Bundle
|
||||
path: |
|
||||
build/installer/Spotube-windows-x86_64-setup.exe
|
||||
build_macos:
|
||||
runs-on: macos-11
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: subosito/flutter-action@v2
|
||||
with:
|
||||
cache: true
|
||||
- run: flutter config --enable-macos-desktop
|
||||
- run: flutter pub get
|
||||
- run: dart bin/create-secrets.dart '${{ secrets.LYRICS_SECRET }}' '${{ secrets.SPOTIFY_SECRET }}'
|
||||
- run: flutter build macos
|
||||
- run: du -sh build/macos/Build/Products/Release/spotube.app
|
||||
- run: npm install -g appdmg
|
||||
- run: appdmg appdmg.json build/Spotube-macos-x86_64.dmg
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: Spotube-Macos-Bundle
|
||||
path: |
|
||||
build/Spotube-macos-x86_64.dmg
|
33
.github/workflows/potential-duplicates.yml
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
name: Detect Potential Duplicates Issues
|
||||
on:
|
||||
issues:
|
||||
types:
|
||||
- opened
|
||||
- edited
|
||||
jobs:
|
||||
run:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: wow-actions/potential-duplicates@v1
|
||||
with:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
# Issue title filter work with anymatch https://www.npmjs.com/package/anymatch.
|
||||
# Any matched issue will stop detection immediately.
|
||||
# You can specify multi filters in each line.
|
||||
filter: ''
|
||||
# Exclude keywords in title before detecting.
|
||||
exclude: ''
|
||||
# Label to set, when potential duplicates are detected.
|
||||
label: potential-duplicate
|
||||
# Get issues with state to compare. Supported state: 'all', 'closed', 'open'.
|
||||
state: all
|
||||
# If similarity is higher than this threshold([0,1]), issue will be marked as duplicate.
|
||||
threshold: 0.6
|
||||
# Reactions to be add to comment when potential duplicates are detected.
|
||||
# Available reactions: "-1", "+1", "confused", "laugh", "heart", "hooray", "rocket", "eyes"
|
||||
reactions: eyes
|
||||
# Comment to post when potential duplicates are detected.
|
||||
comment: >
|
||||
Potential duplicates: {{#issues}}
|
||||
- [#{{ number }}] {{ title }} ({{ accuracy }}%)
|
||||
{{/issues}}
|
37
.github/workflows/pr-lint.yml
vendored
Normal file
@ -0,0 +1,37 @@
|
||||
name: Lint
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
|
||||
env:
|
||||
FLUTTER_VERSION: 3.35.2
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
- uses: subosito/flutter-action@v2
|
||||
with:
|
||||
flutter-version: ${{ env.FLUTTER_VERSION }}
|
||||
|
||||
- name: Dummy Envs
|
||||
run: |
|
||||
envsubst < .env.example > .env
|
||||
env:
|
||||
ENABLE_UPDATE_CHECK: true
|
||||
LASTFM_API_KEY: xxx
|
||||
LASTFM_API_SECRET: xxx
|
||||
RELEASE_CHANNEL: nightly
|
||||
HIDE_DONATIONS: 0
|
||||
|
||||
- name: Configure repo
|
||||
run: |
|
||||
flutter pub get
|
||||
dart run build_runner build --delete-conflicting-outputs
|
||||
|
||||
- name: Lint Dart files
|
||||
run: |
|
||||
dart analyze --no-fatal-warnings
|
290
.github/workflows/release-build.yml
vendored
@ -1,290 +0,0 @@
|
||||
name: Spotube Build & Release
|
||||
on:
|
||||
release:
|
||||
types:
|
||||
- published
|
||||
|
||||
jobs:
|
||||
publish_chocolatey:
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
repository: KRTirtho/flutter_distributor
|
||||
ref: deb-implementation
|
||||
path: build/flutter_distributor
|
||||
- name: Get latest tag
|
||||
id: tag
|
||||
uses: dawidd6/action-get-tag@v1
|
||||
with:
|
||||
# Optionally strip `v` prefix
|
||||
strip_v: true
|
||||
# Replace Version in files
|
||||
- run: |
|
||||
choco install sed make -y
|
||||
sed -i "s/%{{SPOTUBE_VERSION}}%/${{ steps.tag.outputs.tag }}/" windows/runner/Runner.rc
|
||||
sed -i "s/%{{SPOTUBE_VERSION}}%/${{ steps.tag.outputs.tag }}/" choco-struct/tools/VERIFICATION.txt
|
||||
sed -i "s/%{{SPOTUBE_VERSION}}%/${{ steps.tag.outputs.tag }}/" choco-struct/spotube.nuspec
|
||||
|
||||
# Build Windows Executable
|
||||
- uses: subosito/flutter-action@v2.2.0
|
||||
with:
|
||||
cache: true
|
||||
- run: |
|
||||
flutter config --enable-windows-desktop
|
||||
flutter pub get
|
||||
dart bin/create-secrets.dart '${{ secrets.LYRICS_SECRET }}' '${{ secrets.SPOTIFY_SECRET }}'
|
||||
dart pub global activate melos
|
||||
cd build/flutter_distributor && melos bootstrap && cd ../..
|
||||
make innoinstall
|
||||
dart build/flutter_distributor/packages/flutter_distributor/bin/main.dart package --platform=windows --targets=exe --skip-clean
|
||||
|
||||
# Create Chocolatey Package
|
||||
# setting the sha256 hash for new bundle
|
||||
- run: |
|
||||
mv dist/**/spotube-*-windows-setup.exe dist/Spotube-windows-x86_64-setup.exe
|
||||
Set-Variable -Name HASH -Value (Get-FileHash dist\Spotube-windows-x86_64-setup.exe).Hash
|
||||
sed -i "s/%{{WIN_SHA256}}%/$HASH/" choco-struct/tools/VERIFICATION.txt
|
||||
make choco
|
||||
|
||||
- run: mv dist/spotube.*.nupkg dist/Spotube-windows-x86_64.nupkg
|
||||
|
||||
# Publish to Chocolatey Repository
|
||||
- run: |
|
||||
choco apikey -k ${{ secrets.CHOCO_API_KEY }} -s https://push.chocolatey.org/
|
||||
choco push dist/Spotube-windows-x86_64.nupkg
|
||||
echo 'published to community.chocolatey.org'
|
||||
|
||||
# Upload artifacts
|
||||
- uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: Spotube-Windows-Bundle
|
||||
path: dist/
|
||||
|
||||
publish_macos:
|
||||
runs-on: macos-11
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Get latest tag
|
||||
uses: dawidd6/action-get-tag@v1
|
||||
id: tag
|
||||
with:
|
||||
strip_v: true
|
||||
- uses: subosito/flutter-action@v2
|
||||
with:
|
||||
cache: true
|
||||
- run: flutter config --enable-macos-desktop
|
||||
- run: flutter pub get
|
||||
- run: dart bin/create-secrets.dart '${{ secrets.LYRICS_SECRET }}' '${{ secrets.SPOTIFY_SECRET }}'
|
||||
- run: flutter build macos
|
||||
- run: du -sh build/macos/Build/Products/Release/spotube.app
|
||||
- run: npm install -g appdmg
|
||||
# using a versioned path for compatibility in gensums
|
||||
- run: mkdir -p build/${{ steps.tag.outputs.tag }}
|
||||
- run: appdmg appdmg.json build/${{ steps.tag.outputs.tag }}/Spotube-macos-x86_64.dmg
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: Spotube-Macos-Bundle
|
||||
path: |
|
||||
build/${{ steps.tag.outputs.tag }}/Spotube-macos-x86_64.dmg
|
||||
|
||||
publish_linux:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
repository: KRTirtho/flutter_distributor
|
||||
ref: deb-implementation
|
||||
path: build/flutter_distributor
|
||||
- name: Get latest tag
|
||||
id: tag
|
||||
uses: dawidd6/action-get-tag@v1
|
||||
with:
|
||||
strip_v: true
|
||||
- uses: subosito/flutter-action@v2
|
||||
with:
|
||||
cache: true
|
||||
- name: Get current date
|
||||
id: date
|
||||
run: echo "::set-output name=date::$(date +'%Y-%m-%d')"
|
||||
- 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: |
|
||||
wget -O appimage-builder-x86_64.AppImage https://github.com/AppImageCrafters/appimage-builder/releases/download/v1.0.0-beta.1/appimage-builder-1.0.0-677acbd-x86_64.AppImage
|
||||
chmod +x appimage-builder-x86_64.AppImage
|
||||
mv appimage-builder-x86_64.AppImage /usr/local/bin/appimage-builder
|
||||
# replacing & adding new release version with older version
|
||||
- run: |
|
||||
sed -i 's|%{{APPDATA_RELEASE}}%|<release version="${{ steps.tag.outputs.tag }}" date="${{ steps.date.outputs.date }}" />|' linux/com.github.KRTirtho.Spotube.appdata.xml
|
||||
|
||||
- run: |
|
||||
flutter config --enable-linux-desktop
|
||||
flutter pub get
|
||||
dart bin/create-secrets.dart '${{ secrets.LYRICS_SECRET }}' '${{ secrets.SPOTIFY_SECRET }}'
|
||||
dart pub global activate melos
|
||||
cd build/flutter_distributor && melos bootstrap && cd ../..
|
||||
dart build/flutter_distributor/packages/flutter_distributor/bin/main.dart package --platform=linux --targets=deb,appimage --skip-clean
|
||||
make tar
|
||||
- run: |
|
||||
mv build/Spotube-linux-x86_64.tar.xz dist/
|
||||
mv dist/**/spotube-*-linux.deb dist/Spotube-linux-x86_64.deb
|
||||
mv dist/**/spotube-*-linux.AppImage dist/Spotube-linux-x86_64.AppImage
|
||||
- uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: Spotube-Linux-Bundle
|
||||
path: dist/
|
||||
|
||||
publish_android:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
repository: KRTirtho/flutter_distributor
|
||||
ref: deb-implementation
|
||||
path: build/flutter_distributor
|
||||
- name: Get latest tag
|
||||
id: tag
|
||||
uses: dawidd6/action-get-tag@v1
|
||||
with:
|
||||
strip_v: true
|
||||
- uses: subosito/flutter-action@v2
|
||||
with:
|
||||
cache: true
|
||||
- run: |
|
||||
sudo apt-get update -y
|
||||
sudo apt-get install -y 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: |
|
||||
flutter pub get
|
||||
dart bin/create-secrets.dart '${{ secrets.LYRICS_SECRET }}' '${{ secrets.SPOTIFY_SECRET }}'
|
||||
dart pub global activate melos
|
||||
cd build/flutter_distributor && melos bootstrap && cd ../..
|
||||
dart build/flutter_distributor/packages/flutter_distributor/bin/main.dart package --platform=android --targets=apk --skip-clean
|
||||
- run: |
|
||||
mv dist/**/spotube-*-android.apk dist/Spotube-android-all-arch.apk
|
||||
- uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: Spotube-Android-Bundle
|
||||
path: dist/
|
||||
|
||||
update_release:
|
||||
needs:
|
||||
- publish_chocolatey
|
||||
- publish_macos
|
||||
- publish_linux
|
||||
- publish_android
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
steps:
|
||||
- uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: Spotube-Windows-Bundle
|
||||
path: ./Spotube-Windows-Bundle
|
||||
- uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: Spotube-Macos-Bundle
|
||||
path: ./Spotube-Macos-Bundle
|
||||
- uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: Spotube-Linux-Bundle
|
||||
path: ./Spotube-Linux-Bundle
|
||||
- uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: Spotube-Android-Bundle
|
||||
path: ./Spotube-Android-Bundle
|
||||
- name: Get latest tag
|
||||
id: tag
|
||||
uses: dawidd6/action-get-tag@v1
|
||||
with:
|
||||
strip_v: true
|
||||
- run: sudo apt-get install tree -y
|
||||
# generating checksums for all the binary
|
||||
- run: |
|
||||
tree .
|
||||
md5sum ./Spotube-Windows-Bundle/*.{exe,nupkg} > RELEASE.md5sum
|
||||
md5sum ./Spotube-Macos-Bundle/*.dmg > RELEASE.md5sum
|
||||
md5sum ./Spotube-Linux-Bundle/*.{AppImage,tar.xz,deb} > RELEASE.md5sum
|
||||
md5sum ./Spotube-Android-Bundle/*.apk > RELEASE.md5sum
|
||||
sha256sum ./Spotube-Macos-Bundle/*.dmg > RELEASE.sha256sum
|
||||
sha256sum ./Spotube-Windows-Bundle/*.{exe,nupkg} > RELEASE.sha256sum
|
||||
sha256sum ./Spotube-Linux-Bundle/*.{AppImage,tar.xz,deb} > RELEASE.sha256sum
|
||||
sha256sum ./Spotube-Android-Bundle/*.apk > RELEASE.sha256sum
|
||||
sed -i 's|Spotube-.*-Bundle/||' RELEASE.sha256sum RELEASE.md5sum
|
||||
# Upload release binary
|
||||
- uses: ncipollo/release-action@v1
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
tag: v${{ steps.tag.outputs.tag }}
|
||||
omitBodyDuringUpdate: true
|
||||
omitNameDuringUpdate: true
|
||||
omitPrereleaseDuringUpdate: true
|
||||
allowUpdates: true
|
||||
artifacts: Spotube-Windows-Bundle/*,Spotube-Macos-Bundle/*,Spotube-Linux-Bundle/*,Spotube-Android-Bundle/*,RELEASE.sha256sum,RELEASE.md5sum
|
||||
|
||||
# publish_winget:
|
||||
# needs: update_release
|
||||
# runs-on: windows-latest
|
||||
# steps:
|
||||
# - name: Get latest tag
|
||||
# id: tag
|
||||
# uses: dawidd6/action-get-tag@v1
|
||||
# with:
|
||||
# strip_v: true
|
||||
# - run: |
|
||||
# winget install wingetcreate --silent
|
||||
# choco install tree -y
|
||||
# wingetcreate update KRTirtho.Spotube --urls https://github.com/KRTirtho/spotube/releases/download/v${{ steps.tag.outputs.tag }}/Spotube-windows-x86_64-setup.exe https://github.com/KRTirtho/spotube/releases/download/v${{ steps.tag.outputs.tag }}/Spotube-windows-x86_64-setup.exe --version ${{ steps.tag.outputs.tag }} --token ${{ secrets.GITHUB_TOKEN }} --submit
|
||||
|
||||
publish_flathub:
|
||||
needs: update_release
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
repository: flathub/com.github.KRTirtho.Spotube
|
||||
token: ${{ secrets.FLATHUB_TOKEN }}
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
path: spotube
|
||||
- name: Get latest tag
|
||||
id: tag
|
||||
uses: dawidd6/action-get-tag@v1
|
||||
with:
|
||||
strip_v: true
|
||||
- run: |
|
||||
python3 spotube/scripts/update_flathub_version.py ${{ steps.tag.outputs.tag }}
|
||||
- uses: EndBug/add-and-commit@v9
|
||||
with:
|
||||
message: v${{ steps.tag.outputs.tag }} Update
|
||||
push: origin master
|
||||
|
||||
publish_aur:
|
||||
needs: update_release
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Get latest tag
|
||||
id: tag
|
||||
uses: dawidd6/action-get-tag@v1
|
||||
with:
|
||||
strip_v: true
|
||||
- uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: Spotube-Linux-Bundle
|
||||
path: ./Spotube-Linux-Bundle
|
||||
- run: |
|
||||
sed -i "s/%{{SPOTUBE_VERSION}}%/${{ steps.tag.outputs.tag }}/" aur-struct/PKGBUILD
|
||||
sed -i "s/%{{PKGREL}}%/1/" aur-struct/PKGBUILD
|
||||
sed -i "s/%{{LINUX_MD5}}%/`md5sum Spotube-Linux-Bundle/Spotube-linux-x86_64.tar.xz | awk '{print $1}'`/" aur-struct/PKGBUILD
|
||||
- uses: KSXGitHub/github-actions-deploy-aur@v2.2.5
|
||||
with:
|
||||
pkgname: spotube-bin
|
||||
pkgbuild: aur-struct/PKGBUILD
|
||||
commit_username: ${{ secrets.AUR_USERNAME }}
|
||||
commit_email: ${{ secrets.AUR_EMAIL }}
|
||||
ssh_private_key: ${{ secrets.AUR_SSH_PRIVATE_KEY }}
|
||||
commit_message: Updated to v${{ steps.tag.outputs.tag }}
|
137
.github/workflows/spotube-publish-binary.yml
vendored
Normal file
@ -0,0 +1,137 @@
|
||||
name: Spotube Publish Binary
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
version:
|
||||
description: Version to publish (x.x.x)
|
||||
default: 4.0.0
|
||||
required: true
|
||||
dry_run:
|
||||
description: Dry run
|
||||
required: true
|
||||
type: boolean
|
||||
default: true
|
||||
jobs:
|
||||
description: Jobs to run (flathub,aur,winget,chocolatey,playstore)
|
||||
required: true
|
||||
type: string
|
||||
default: "flathub,aur,winget,chocolatey,playstore"
|
||||
|
||||
jobs:
|
||||
flathub:
|
||||
runs-on: ubuntu-22.04
|
||||
if: contains(inputs.jobs, 'flathub')
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
repository: KRTirtho/com.github.KRTirtho.Spotube
|
||||
token: ${{ secrets.FLATHUB_TOKEN }}
|
||||
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
path: spotube
|
||||
|
||||
- name: Update flathub version
|
||||
run: |
|
||||
python3 spotube/scripts/update_flathub_version.py ${{ inputs.version }}
|
||||
rm -rf spotube
|
||||
git config --global user.email "krtirtho@gmail.com"
|
||||
git config --global user.name "Kingkor Roy Tirtho"
|
||||
git add .
|
||||
git commit -m "v${{ inputs.version }} Update"
|
||||
git branch update-${{ inputs.version }}
|
||||
git switch update-${{ inputs.version }}
|
||||
|
||||
- name: Push to flathub
|
||||
if: ${{ !inputs.dry_run }}
|
||||
run: git push -u origin update-${{ inputs.version }}
|
||||
|
||||
aur:
|
||||
runs-on: ubuntu-22.04
|
||||
if: contains(inputs.jobs, 'aur')
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: dsaltares/fetch-gh-release-asset@master
|
||||
with:
|
||||
version: tags/v${{ inputs.version }} # mind the "v" prefix
|
||||
file: spotube-linux-${{inputs.version}}-x86_64.tar.xz
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Update PKGBUILD versions
|
||||
run: |
|
||||
sed -i "s/%{{SPOTUBE_VERSION}}%/${{ inputs.version }}/" aur-struct/PKGBUILD
|
||||
sed -i "s/%{{PKGREL}}%/1/" aur-struct/PKGBUILD
|
||||
sed -i "s/%{{LINUX_MD5}}%/`md5sum spotube-linux-${{inputs.version}}-x86_64.tar.xz | awk '{print $1}'`/" aur-struct/PKGBUILD
|
||||
|
||||
- name: Release to AUR
|
||||
if: ${{ !inputs.dry_run }}
|
||||
uses: KSXGitHub/github-actions-deploy-aur@v2.7.2
|
||||
with:
|
||||
pkgname: spotube-bin
|
||||
pkgbuild: aur-struct/PKGBUILD
|
||||
commit_username: ${{ secrets.AUR_USERNAME }}
|
||||
commit_email: ${{ secrets.AUR_EMAIL }}
|
||||
ssh_private_key: ${{ secrets.AUR_SSH_PRIVATE_KEY }}
|
||||
commit_message: Updated to v${{ inputs.version }}
|
||||
|
||||
winget:
|
||||
runs-on: ubuntu-latest
|
||||
if: contains(inputs.jobs, 'winget')
|
||||
steps:
|
||||
- name: Release winget package
|
||||
if: ${{ !inputs.dry_run }}
|
||||
uses: vedantmgoyal9/winget-releaser@main
|
||||
with:
|
||||
version: ${{ inputs.version }}
|
||||
release-tag: v${{ inputs.version }}
|
||||
identifier: KRTirtho.Spotube
|
||||
token: ${{ secrets.WINGET_TOKEN }}
|
||||
|
||||
chocolatey:
|
||||
runs-on: windows-latest
|
||||
if: contains(inputs.jobs, 'chocolatey')
|
||||
steps:
|
||||
- uses: dsaltares/fetch-gh-release-asset@master
|
||||
with:
|
||||
version: tags/v${{ inputs.version }} # mind the "v" prefix
|
||||
file: Spotube-windows-x86_64.nupkg
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Set up Chocolatey
|
||||
run: choco apikey -k ${{ secrets.CHOCO_API_KEY }} --source https://push.chocolatey.org/
|
||||
|
||||
- name: Publish to Chocolatey Repository
|
||||
if: ${{ !inputs.dry_run }}
|
||||
run: choco push Spotube-windows-x86_64.nupkg --source https://push.chocolatey.org/
|
||||
|
||||
playstore:
|
||||
runs-on: ubuntu-latest
|
||||
if: contains(inputs.jobs, 'playstore')
|
||||
steps:
|
||||
- name: Tagname (workflow dispatch)
|
||||
run: echo 'TAG_NAME=${{inputs.version}}' >> $GITHUB_ENV
|
||||
|
||||
- uses: robinraju/release-downloader@main
|
||||
with:
|
||||
repository: KRTirtho/spotube
|
||||
tag: v${{ env.TAG_NAME }}
|
||||
tarBall: false
|
||||
zipBall: false
|
||||
out-file-path: dist
|
||||
fileName: "Spotube-playstore-all-arch.aab"
|
||||
|
||||
- name: Create service-account.json
|
||||
run: |
|
||||
echo "${{ secrets.GOOGLE_PLAY_SERVICE_ACCOUNT_BASE64 }}" | base64 -d > service-account.json
|
||||
|
||||
- name: Upload Android Release to Play Store
|
||||
if: ${{!inputs.dry_run}}
|
||||
uses: r0adkll/upload-google-play@v1
|
||||
with:
|
||||
serviceAccountJson: ./service-account.json
|
||||
releaseFiles: ./dist/Spotube-playstore-all-arch.aab
|
||||
packageName: oss.krtirtho.spotube
|
||||
track: production
|
||||
status: draft
|
||||
releaseName: ${{ env.TAG_NAME }}
|
195
.github/workflows/spotube-release-binary.yml
vendored
Normal file
@ -0,0 +1,195 @@
|
||||
name: Spotube Release Binary
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
channel:
|
||||
type: choice
|
||||
options:
|
||||
- stable
|
||||
- nightly
|
||||
default: nightly
|
||||
description: The release channel
|
||||
debug:
|
||||
type: boolean
|
||||
default: false
|
||||
description: Debug with SSH toggle
|
||||
required: false
|
||||
dry_run:
|
||||
type: boolean
|
||||
default: false
|
||||
description: Dry run without uploading to release
|
||||
|
||||
env:
|
||||
FLUTTER_VERSION: 3.35.2
|
||||
FLUTTER_CHANNEL: master
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
build_platform:
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- os: ubuntu-22.04
|
||||
platform: linux
|
||||
arch: x86
|
||||
files: |
|
||||
dist/Spotube-linux-x86_64.deb
|
||||
dist/Spotube-linux-x86_64.rpm
|
||||
dist/spotube-linux-*-x86_64.tar.xz
|
||||
- os: ubuntu-22.04-arm
|
||||
platform: linux
|
||||
arch: arm64
|
||||
files: |
|
||||
dist/Spotube-linux-aarch64.deb
|
||||
dist/spotube-linux-*-aarch64.tar.xz
|
||||
- os: ubuntu-22.04
|
||||
platform: android
|
||||
arch: all
|
||||
files: |
|
||||
build/Spotube-android-all-arch.apk
|
||||
build/Spotube-playstore-all-arch.aab
|
||||
- os: windows-latest
|
||||
platform: windows
|
||||
arch: x86
|
||||
files: |
|
||||
dist/Spotube-windows-x86_64.nupkg
|
||||
dist/Spotube-windows-x86_64-setup.exe
|
||||
- os: macos-14
|
||||
platform: ios
|
||||
arch: all
|
||||
files: |
|
||||
Spotube-iOS.ipa
|
||||
- os: macos-14
|
||||
platform: macos
|
||||
arch: all
|
||||
files: |
|
||||
build/Spotube-macos-universal.dmg
|
||||
build/Spotube-macos-universal.pkg
|
||||
runs-on: ${{matrix.os}}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: subosito/flutter-action@v2.18.0
|
||||
with:
|
||||
flutter-version: ${{ env.FLUTTER_VERSION }}
|
||||
channel: ${{ env.FLUTTER_CHANNEL }}
|
||||
cache: true
|
||||
git-source: https://github.com/flutter/flutter.git
|
||||
|
||||
- name: Setup Java
|
||||
if: ${{matrix.platform == 'android'}}
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: "zulu"
|
||||
java-version: "17"
|
||||
cache: "gradle"
|
||||
check-latest: true
|
||||
|
||||
- name: Setup Rust toolchain
|
||||
uses: dtolnay/rust-toolchain@stable
|
||||
with:
|
||||
toolchain: stable
|
||||
|
||||
- name: Install Xcode
|
||||
if: ${{matrix.platform == 'ios'}}
|
||||
uses: maxim-lobanov/setup-xcode@v1
|
||||
with:
|
||||
xcode-version: "16.2"
|
||||
|
||||
- name: Install ${{matrix.platform}} dependencies
|
||||
run: |
|
||||
flutter pub get
|
||||
dart cli/cli.dart install-dependencies --platform=${{matrix.platform}}
|
||||
|
||||
- name: Sign Apk
|
||||
if: ${{matrix.platform == 'android'}}
|
||||
run: |
|
||||
echo '${{ secrets.KEYSTORE }}' | base64 --decode > android/app/upload-keystore.jks
|
||||
echo '${{ secrets.KEY_PROPERTIES }}' > android/key.properties
|
||||
|
||||
- name: Build ${{matrix.platform}} binaries
|
||||
run: dart cli/cli.dart build --arch=${{matrix.arch}} ${{matrix.platform}}
|
||||
env:
|
||||
CHANNEL: ${{inputs.channel}}
|
||||
DOTENV: ${{secrets.DOTENV_RELEASE}}
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
if-no-files-found: error
|
||||
name: ${{matrix.platform}}-${{matrix.arch}}
|
||||
path: ${{matrix.files}}
|
||||
|
||||
- name: Debug With SSH When fails
|
||||
if: ${{ failure() && inputs.debug && inputs.channel == 'nightly' }}
|
||||
uses: mxschmitt/action-tmate@v3
|
||||
with:
|
||||
limit-access-to-actor: true
|
||||
|
||||
upload:
|
||||
runs-on: ubuntu-22.04
|
||||
needs:
|
||||
- build_platform
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
path: ./Spotube-Release-Binaries
|
||||
|
||||
- name: Install dependencies
|
||||
run: sudo apt-get install tree -y
|
||||
|
||||
- name: Generate Checksums
|
||||
run: |
|
||||
tree .
|
||||
find Spotube-Release-Binaries -type f -exec md5sum {} \; >> RELEASE.md5sum
|
||||
find Spotube-Release-Binaries -type f -exec sha256sum {} \; >> RELEASE.sha256sum
|
||||
sed -i 's|Spotube-Release-Binaries/.*/\([^/]*\)$|\1|' RELEASE.sha256sum RELEASE.md5sum
|
||||
sed -i 's|Spotube-Release-Binaries/||' RELEASE.sha256sum RELEASE.md5sum
|
||||
|
||||
- name: Extract pubspec version
|
||||
run: |
|
||||
echo "PUBSPEC_VERSION=$(grep -oP 'version:\s*\K[^+]+(?=\+)' pubspec.yaml)" >> $GITHUB_ENV
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
if-no-files-found: error
|
||||
name: sums
|
||||
path: |
|
||||
RELEASE.md5sum
|
||||
RELEASE.sha256sum
|
||||
|
||||
- name: Upload Release Binaries (stable)
|
||||
if: ${{ !inputs.dry_run && inputs.channel == 'stable' }}
|
||||
uses: ncipollo/release-action@v1
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
tag: v${{ env.PUBSPEC_VERSION }} # mind the "v" prefix
|
||||
omitBodyDuringUpdate: true
|
||||
omitNameDuringUpdate: true
|
||||
omitPrereleaseDuringUpdate: true
|
||||
allowUpdates: true
|
||||
artifacts: Spotube-Release-Binaries/**/*,RELEASE.sha256sum,RELEASE.md5sum
|
||||
|
||||
- name: Upload Release Binaries (nightly)
|
||||
if: ${{ !inputs.dry_run && inputs.channel == 'nightly' }}
|
||||
uses: ncipollo/release-action@v1
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
tag: nightly
|
||||
omitBodyDuringUpdate: true
|
||||
omitNameDuringUpdate: true
|
||||
omitPrereleaseDuringUpdate: true
|
||||
allowUpdates: true
|
||||
artifacts: Spotube-Release-Binaries/**/*,RELEASE.sha256sum,RELEASE.md5sum
|
||||
body: |
|
||||
Build Number: ${{github.run_number}}
|
||||
|
||||
Nightly release includes newest features but may contain bugs
|
||||
It is preferred to use the stable version unless you know what you're doing
|
||||
|
||||
- name: Debug With SSH When fails
|
||||
if: ${{ failure() && inputs.debug && inputs.channel == 'nightly' }}
|
||||
uses: mxschmitt/action-tmate@v3
|
||||
with:
|
||||
limit-access-to-actor: true
|
17
.gitignore
vendored
@ -32,7 +32,6 @@
|
||||
/build/
|
||||
|
||||
# Web related
|
||||
lib/generated_plugin_registrant.dart
|
||||
|
||||
# Symbolication related
|
||||
app.*.symbols
|
||||
@ -45,7 +44,6 @@ app.*.map.json
|
||||
/android/app/profile
|
||||
/android/app/release
|
||||
|
||||
|
||||
*.pkg.tar.zst
|
||||
/aur-struct/*.tar
|
||||
/aur-struct/src
|
||||
@ -68,9 +66,20 @@ installer.exe
|
||||
|
||||
# secrets
|
||||
*.env
|
||||
lib/models/generated_secrets.dart
|
||||
lib/collections/env.g.dart
|
||||
help.txt
|
||||
secrets.json
|
||||
|
||||
dist
|
||||
appimage-build
|
||||
|
||||
android/key.properties
|
||||
|
||||
**/pb_data
|
||||
|
||||
tm.json
|
||||
|
||||
# FVM Version Cache
|
||||
.fvm/
|
||||
|
||||
android/build
|
||||
android/app/.cxx
|
||||
|
24
.metadata
@ -4,7 +4,27 @@
|
||||
# This file should be version controlled and should not be manually edited.
|
||||
|
||||
version:
|
||||
revision: 77d935af4db863f6abd0b9c31c7e6df2a13de57b
|
||||
channel: stable
|
||||
revision: "d7b523b356d15fb81e7d340bbe52b47f93937323"
|
||||
channel: "stable"
|
||||
|
||||
project_type: app
|
||||
|
||||
# Tracks metadata for the flutter migrate command
|
||||
migration:
|
||||
platforms:
|
||||
- platform: root
|
||||
create_revision: d7b523b356d15fb81e7d340bbe52b47f93937323
|
||||
base_revision: d7b523b356d15fb81e7d340bbe52b47f93937323
|
||||
- platform: windows
|
||||
create_revision: d7b523b356d15fb81e7d340bbe52b47f93937323
|
||||
base_revision: d7b523b356d15fb81e7d340bbe52b47f93937323
|
||||
|
||||
# User provided section
|
||||
|
||||
# List of Local paths (relative to this file) that should be
|
||||
# ignored by the migrate tool.
|
||||
#
|
||||
# Files that are not part of the templates will be ignored by default.
|
||||
unmanaged_files:
|
||||
- 'lib/main.dart'
|
||||
- 'ios/Runner.xcodeproj/project.pbxproj'
|
||||
|
3
.vscode/c_cpp_properties.json
vendored
@ -14,7 +14,8 @@
|
||||
"compilerPath": "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community\\VC\\Tools\\MSVC\\14.29.30133\\bin\\Hostx64\\x64\\cl.exe",
|
||||
"cStandard": "c17",
|
||||
"cppStandard": "c++17",
|
||||
"intelliSenseMode": "windows-msvc-x64"
|
||||
"intelliSenseMode": "windows-msvc-x64",
|
||||
"configurationProvider": "ms-vscode.makefile-tools"
|
||||
}
|
||||
],
|
||||
"version": 4
|
||||
|
51
.vscode/launch.json
vendored
@ -2,12 +2,57 @@
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Flutter",
|
||||
"name": "spotube",
|
||||
"type": "dart",
|
||||
"request": "launch",
|
||||
"program": "lib/main.dart"
|
||||
"program": "lib/main.dart",
|
||||
},
|
||||
{
|
||||
"name": "spotube (mobile)",
|
||||
"type": "dart",
|
||||
"request": "launch",
|
||||
"program": "lib/main.dart",
|
||||
"args": [
|
||||
"--flavor",
|
||||
"dev"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "spotube (mobile-skia)",
|
||||
"type": "dart",
|
||||
"request": "launch",
|
||||
"program": "lib/main.dart",
|
||||
"args": [
|
||||
"--flavor",
|
||||
"dev",
|
||||
"--no-enable-impeller"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "spotube (profile)",
|
||||
"type": "dart",
|
||||
"request": "launch",
|
||||
"program": "lib/main.dart",
|
||||
"flutterMode": "profile"
|
||||
},
|
||||
{
|
||||
"name": "spotube (release)",
|
||||
"type": "dart",
|
||||
"request": "launch",
|
||||
"program": "lib/main.dart",
|
||||
"flutterMode": "release"
|
||||
},
|
||||
{
|
||||
"name": "spotube (mobile) (release)",
|
||||
"type": "dart",
|
||||
"request": "launch",
|
||||
"program": "lib/main.dart",
|
||||
"flutterMode": "release",
|
||||
"args": [
|
||||
"--flavor",
|
||||
"dev"
|
||||
]
|
||||
}
|
||||
|
||||
],
|
||||
"compounds": []
|
||||
}
|
33
.vscode/settings.json
vendored
@ -1,3 +1,34 @@
|
||||
{
|
||||
"cmake.configureOnOpen": false
|
||||
"cmake.configureOnOpen": false,
|
||||
"cSpell.words": [
|
||||
"acousticness",
|
||||
"ambiguate",
|
||||
"Amoled",
|
||||
"Buildless",
|
||||
"configurators",
|
||||
"danceability",
|
||||
"fuzzywuzzy",
|
||||
"gapless",
|
||||
"instrumentalness",
|
||||
"isrc",
|
||||
"Mpris",
|
||||
"RGBO",
|
||||
"riverpod",
|
||||
"Scrobblenaut",
|
||||
"shadcn",
|
||||
"skeletonizer",
|
||||
"songlink",
|
||||
"speechiness",
|
||||
"Spotube",
|
||||
"titlebar",
|
||||
"winget"
|
||||
],
|
||||
"editor.formatOnSave": true,
|
||||
"explorer.fileNesting.enabled": true,
|
||||
"explorer.fileNesting.patterns": {
|
||||
"pubspec.yaml": "pubspec.lock,analysis_options.yaml,.packages,.flutter-plugins,.flutter-plugins-dependencies,flutter_launcher_icons*.yaml,flutter_native_splash*.yaml",
|
||||
"README.md": "LICENSE,CODE_OF_CONDUCT.md,CONTRIBUTING.md,SECURITY.md,CONTRIBUTION.md,CHANGELOG.md,PRIVACY_POLICY.md",
|
||||
"*.dart": "${capture}.g.dart,${capture}.freezed.dart"
|
||||
},
|
||||
"dart.flutterSdkPath": ".fvm/versions/3.35.2"
|
||||
}
|
170
.vscode/snippets.code-snippets
vendored
Normal file
@ -0,0 +1,170 @@
|
||||
{
|
||||
"PaginatedState": {
|
||||
"scope": "dart",
|
||||
"prefix": "paginatedState",
|
||||
"description": "Generate a PaginatedState",
|
||||
"body": [
|
||||
"class ${1:Model}State extends PaginatedState<${2:Model}> {",
|
||||
" ${1:Model}State({",
|
||||
" required super.items,",
|
||||
" required super.offset,",
|
||||
" required super.limit,",
|
||||
" required super.hasMore,",
|
||||
" });",
|
||||
" ",
|
||||
" @override",
|
||||
" ${1:Model}State copyWith({",
|
||||
" List<${2:Model}>? items,",
|
||||
" int? offset,",
|
||||
" int? limit,",
|
||||
" bool? hasMore,",
|
||||
" }) {",
|
||||
" return ${1:Model}State(",
|
||||
" items: items ?? this.items,",
|
||||
" offset: offset ?? this.offset,",
|
||||
" limit: limit ?? this.limit,",
|
||||
" hasMore: hasMore ?? this.hasMore,",
|
||||
" );",
|
||||
" }",
|
||||
"}"
|
||||
]
|
||||
},
|
||||
"PaginatedAsyncNotifier": {
|
||||
"scope": "dart",
|
||||
"prefix": "paginatedAsyncNotifier",
|
||||
"description": "Generate a PaginatedAsyncNotifier",
|
||||
"body": [
|
||||
"class ${1:NotifierName}Notifier extends PaginatedAsyncNotifier<${3:Item}, ${2:Model}State> {",
|
||||
" ${1:NotifierName}Notifier() : super();",
|
||||
" ",
|
||||
" @override",
|
||||
" fetch(int offset, int limit) async {",
|
||||
" throw UnimplementedError();",
|
||||
" }",
|
||||
" ",
|
||||
" @override",
|
||||
" build() async {",
|
||||
" throw UnimplementedError();",
|
||||
" }",
|
||||
"}"
|
||||
]
|
||||
},
|
||||
"PaginaitedNotifierWithState": {
|
||||
"scope": "dart",
|
||||
"prefix": "paginatedNotifierWithState",
|
||||
"description": "Generate a PaginatedNotifier with PaginatedState",
|
||||
"body": [
|
||||
"class $1State extends PaginatedState<$2> {",
|
||||
" $1State({",
|
||||
" required super.items,",
|
||||
" required super.offset,",
|
||||
" required super.limit,",
|
||||
" required super.hasMore,",
|
||||
" });",
|
||||
" ",
|
||||
" @override",
|
||||
" $1State copyWith({",
|
||||
" List<$2>? items,",
|
||||
" int? offset,",
|
||||
" int? limit,",
|
||||
" bool? hasMore,",
|
||||
" }) {",
|
||||
" return $1State(",
|
||||
" items: items ?? this.items,",
|
||||
" offset: offset ?? this.offset,",
|
||||
" limit: limit ?? this.limit,",
|
||||
" hasMore: hasMore ?? this.hasMore,",
|
||||
" );",
|
||||
" }",
|
||||
"}",
|
||||
" ",
|
||||
"class $1Notifier",
|
||||
" extends PaginatedAsyncNotifier<$2, $1State> {",
|
||||
" $1Notifier() : super();",
|
||||
" ",
|
||||
" @override",
|
||||
" fetch(int offset, int limit) async {",
|
||||
" throw UnimplementedError();",
|
||||
" }",
|
||||
" ",
|
||||
" @override",
|
||||
" build() async {",
|
||||
" throw UnimplementedError();",
|
||||
" }",
|
||||
"}",
|
||||
" ",
|
||||
"final ${1/(.*)/${1:/camelcase}/}Provider = AsyncNotifierProvider<$1Notifier, $1State>(",
|
||||
" ()=> $1Notifier(),",
|
||||
");"
|
||||
]
|
||||
},
|
||||
"FamilyPaginatedAsyncNotifier": {
|
||||
"scope": "dart",
|
||||
"prefix": "familyPaginatedAsyncNotifier",
|
||||
"description": "Generate a FamilyPaginatedAsyncNotifier",
|
||||
"body": [
|
||||
"class ${1:NotifierName}Notifier extends FamilyPaginatedAsyncNotifier<${3:Item}, ${2:Model}State, {$4:Arg}> {",
|
||||
" ${1:NotifierName}Notifier() : super();",
|
||||
" ",
|
||||
" @override",
|
||||
" fetch(arg, offset, limit) async {",
|
||||
" throw UnimplementedError();",
|
||||
" }",
|
||||
" ",
|
||||
" @override",
|
||||
" build(arg) async {",
|
||||
" throw UnimplementedError();",
|
||||
" }",
|
||||
"}"
|
||||
]
|
||||
},
|
||||
"FamilyPaginaitedNotifierWithState": {
|
||||
"scope": "dart",
|
||||
"prefix": "familyPaginatedNotifierWithState",
|
||||
"description": "Generate a FamilyPaginatedAsyncNotifier with PaginatedState",
|
||||
"body": [
|
||||
"class $1State extends PaginatedState<$2> {",
|
||||
" $1State({",
|
||||
" required super.items,",
|
||||
" required super.offset,",
|
||||
" required super.limit,",
|
||||
" required super.hasMore,",
|
||||
" });",
|
||||
" ",
|
||||
" @override",
|
||||
" $1State copyWith({",
|
||||
" List<$2>? items,",
|
||||
" int? offset,",
|
||||
" int? limit,",
|
||||
" bool? hasMore,",
|
||||
" }) {",
|
||||
" return $1State(",
|
||||
" items: items ?? this.items,",
|
||||
" offset: offset ?? this.offset,",
|
||||
" limit: limit ?? this.limit,",
|
||||
" hasMore: hasMore ?? this.hasMore,",
|
||||
" );",
|
||||
" }",
|
||||
"}",
|
||||
" ",
|
||||
"class $1Notifier",
|
||||
" extends FamilyPaginatedAsyncNotifier<$2, $1State, $3> {",
|
||||
" $1Notifier() : super();",
|
||||
" ",
|
||||
" @override",
|
||||
" fetch(arg, offset, limit) async {",
|
||||
" throw UnimplementedError();",
|
||||
" }",
|
||||
" ",
|
||||
" @override",
|
||||
" build(arg) async {",
|
||||
" throw UnimplementedError();",
|
||||
" }",
|
||||
"}",
|
||||
" ",
|
||||
"final ${1/(.*)/${1:/camelcase}/}Provider = AsyncNotifierProviderFamily<$1Notifier, $1State, $3>(",
|
||||
" ()=> $1Notifier(),",
|
||||
");"
|
||||
]
|
||||
},
|
||||
}
|
@ -1 +0,0 @@
|
||||
{"version":1,"script":["rm -rf AppDir || true","cp -r build/linux/x64/release/bundle AppDir","mkdir -p AppDir/usr/share/icons/hicolor/64x64/apps/","cp assets/spotube-logo.png AppDir/usr/share/icons/hicolor/"],"AppDir":{"path":"AppDir","app_info":{"id":"oss.krtirtho.spotube","icon":"spotube-logo","name":"spotube","version":"2.0.0+8","exec":"spotube","exec_args":"$@"},"apt":{"arch":"amd64","allow_unauthenticated":true,"sources":[{"sourceline":"deb http://archive.ubuntu.com/ubuntu/ hirsute main restricted"},{"sourceline":"deb http://archive.ubuntu.com/ubuntu/ hirsute-updates main restricted"},{"sourceline":"deb http://archive.ubuntu.com/ubuntu/ hirsute universe"},{"sourceline":"deb http://archive.ubuntu.com/ubuntu/ hirsute-updates universe"},{"sourceline":"deb http://archive.ubuntu.com/ubuntu/ hirsute multiverse"},{"sourceline":"deb http://archive.ubuntu.com/ubuntu/ hirsute-updates multiverse"},{"sourceline":"deb http://archive.ubuntu.com/ubuntu/ hirsute-backports main restricted universe multiverse"},{"sourceline":"deb http://security.ubuntu.com/ubuntu hirsute-security main restricted"},{"sourceline":"deb http://security.ubuntu.com/ubuntu hirsute-security universe"},{"sourceline":"deb http://security.ubuntu.com/ubuntu hirsute-security multiverse"}],"include":["libkeybinder-3.0-0"],"exclude":["libx11-6","libgtk-3-0","libglib2.0-0","libc6"]},"files":{"include":[],"exclude":[]}},"AppImage":{"arch":"x86_64","update-information":"guess"}}
|
979
CHANGELOG.md
@ -5,6 +5,7 @@ First off, thanks for taking the time to contribute! ❤️
|
||||
All types of contributions are encouraged and valued. See the [Table of Contents](#table-of-contents) for different ways to help and details about how this project handles them. Please make sure to read the relevant section before making your contribution. It will make it a lot easier for us maintainers and smooth out the experience for all involved. The community looks forward to your contributions. 🎉
|
||||
|
||||
> And if you like the project, but just don't have time to contribute, that's fine. There are other easy ways to support the project and show your appreciation, which we would also be very happy about:
|
||||
>
|
||||
> - Star the project
|
||||
> - Tweet about it
|
||||
> - Refer this project in your project's readme
|
||||
@ -12,21 +13,26 @@ All types of contributions are encouraged and valued. See the [Table of Contents
|
||||
|
||||
## Table of Contents
|
||||
|
||||
- [Contributing to Spotube](#contributing-to-spotube)
|
||||
- [Table of Contents](#table-of-contents)
|
||||
- [Code of Conduct](#code-of-conduct)
|
||||
- [I Have a Question](#i-have-a-question)
|
||||
- [I Want To Contribute](#i-want-to-contribute)
|
||||
- [Reporting Bugs](#reporting-bugs)
|
||||
- [Before Submitting a Bug Report](#before-submitting-a-bug-report)
|
||||
- [How Do I Submit a Good Bug Report?](#how-do-i-submit-a-good-bug-report)
|
||||
- [Suggesting Enhancements](#suggesting-enhancements)
|
||||
- [Before Submitting an Enhancement](#before-submitting-an-enhancement)
|
||||
- [How Do I Submit a Good Enhancement Suggestion?](#how-do-i-submit-a-good-enhancement-suggestion)
|
||||
- [Your First Code Contribution](#your-first-code-contribution)
|
||||
|
||||
- [Submit Translations](#submit-translations)
|
||||
|
||||
## Code of Conduct
|
||||
|
||||
This project and everyone participating in it is governed by the
|
||||
[Spotube Code of Conduct](https://github.com/KRTirtho/spotubeblob/master/CODE_OF_CONDUCT.md).
|
||||
[Spotube Code of Conduct](https://github.com/KRTirtho/spotube/blob/master/CODE_OF_CONDUCT.md).
|
||||
By participating, you are expected to uphold this code. Please report unacceptable behavior
|
||||
to <>.
|
||||
|
||||
to krtirtho@gmail.com.
|
||||
|
||||
## I Have a Question
|
||||
|
||||
@ -45,11 +51,11 @@ We will then take care of the issue as soon as possible.
|
||||
## I Want To Contribute
|
||||
|
||||
> ### Legal Notice
|
||||
>
|
||||
> When contributing to this project, you must agree that you have authored 100% of the content, that you have the necessary rights to the content and that the content you contribute may be provided under the project license.
|
||||
|
||||
### Reporting Bugs
|
||||
|
||||
|
||||
#### Before Submitting a Bug Report
|
||||
|
||||
A good bug report shouldn't leave others needing to chase you up for more information. Therefore, we ask you to investigate carefully, collect information and describe the issue in detail in your report. Please complete the following steps in advance to help us fix any potential bug as fast as possible.
|
||||
@ -69,12 +75,11 @@ A good bug report shouldn't leave others needing to chase you up for more inform
|
||||
|
||||
> You must never report security related issues, vulnerabilities or bugs including sensitive information to the issue tracker, or elsewhere in public. Instead sensitive bugs must be sent by email to
|
||||
|
||||
|
||||
We use GitHub issues to track bugs and errors. If you run into an issue with the project:
|
||||
|
||||
- Open an [Issue](https://github.com/KRTirtho/spotube/issues/new). (Since we can't be sure at this point whether it is a bug or not, we ask you not to talk about a bug yet and not to label the issue.)
|
||||
- Explain the behavior you would expect and the actual behavior.
|
||||
- Please provide as much context as possible and describe the *reproduction steps* that someone else can follow to recreate the issue on their own. This usually includes your code. For good bug reports you should isolate the problem and create a reduced test case.
|
||||
- Please provide as much context as possible and describe the _reproduction steps_ that someone else can follow to recreate the issue on their own. This usually includes your code. For good bug reports you should isolate the problem and create a reduced test case.
|
||||
- Provide the information you collected in the previous section.
|
||||
|
||||
Once it's filed:
|
||||
@ -83,12 +88,12 @@ Once it's filed:
|
||||
- A team member will try to reproduce the issue with your provided steps. If there are no reproduction steps or no obvious way to reproduce the issue, the team will ask you for those steps and mark the issue as `needs-repro`. Bugs with the `needs-repro` tag will not be addressed until they are reproduced.
|
||||
- If the team is able to reproduce the issue, it will be marked `needs-fix`, as well as possibly other tags (such as `critical`), and the issue will be left to be [implemented by someone](#your-first-code-contribution).
|
||||
|
||||
|
||||
### Suggesting Enhancements
|
||||
|
||||
This section guides you through submitting an enhancement suggestion for Spotube, **including completely new features and minor improvements to existing functionality**. Following these guidelines will help maintainers and the community to understand your suggestion and find related suggestions.
|
||||
|
||||
<!-- omit in toc -->
|
||||
|
||||
#### Before Submitting an Enhancement
|
||||
|
||||
- Make sure that you are using the latest version.
|
||||
@ -97,6 +102,7 @@ This section guides you through submitting an enhancement suggestion for Spotube
|
||||
- Find out whether your idea fits with the scope and aims of the project. It's up to you to make a strong case to convince the project's developers of the merits of this feature. Keep in mind that we want features that will be useful to the majority of our users and not just a small subset
|
||||
|
||||
<!-- omit in toc -->
|
||||
|
||||
#### How Do I Submit a Good Enhancement Suggestion?
|
||||
|
||||
Enhancement suggestions are tracked as [GitHub issues](https://github.com/KRTirtho/spotube/issues).
|
||||
@ -109,36 +115,52 @@ Enhancement suggestions are tracked as [GitHub issues](https://github.com/KRTirt
|
||||
|
||||
### Your First Code Contribution
|
||||
|
||||
<!-- Download -->
|
||||
|
||||
Do the following:
|
||||
- Download the latest Flutter SDK (>=2.15.1) & enable desktop support
|
||||
|
||||
- Install [Dart](https://dart.dev/get-dart) and [fvm](https://fvm.app/documentation/getting-started/installation)
|
||||
- Install Development dependencies in linux
|
||||
- `libwebkit2gtk-4.0-dev`, `libkeybinder-3.0-0` & `libkeybinder-3.0-dev` (for Debian/Ubuntu)
|
||||
- `webkit2gtk` & `libkeybinder3` (for Arch/Manjaro)
|
||||
- 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:
|
||||
```jsoc name="secrets.json"
|
||||
{
|
||||
"LYRICS_SECRET": [
|
||||
"Bo3LQEMcL2xUAJ6yCfQowV6f8K78s9J9FLa67AsyWmvhkP9LWikkgcEyFrzvs7jsR",
|
||||
"HiLHxLj8uv2VhBZfq9BQ9HVrWQk5Jc8aneMZX8RV4KjTmC387K692xrbNK35c8Qe4",
|
||||
],
|
||||
"SPOTIFY_SECRET": [
|
||||
{
|
||||
"clientId": "9ed19daf-c7a2-4c28-91ac-2c5283ad86cf",
|
||||
"clientSecret": "236d5822-820e-457e-b18c-10e258c9386b"
|
||||
},
|
||||
{
|
||||
"clientId": "b4769027-e048-4485-8f0b-b8a336f2cd97",
|
||||
"clientSecret": "41df6ea4-eba2-4d42-b7be-6f727555fccc"
|
||||
},
|
||||
]
|
||||
}
|
||||
- Debian (>=12/Bookworm)/Ubuntu
|
||||
```bash
|
||||
$ apt-get install mpv libmpv-dev libappindicator3-1 gir1.2-appindicator3-0.1 libappindicator3-dev libsecret-1-0 libjsoncpp25 libsecret-1-dev libjsoncpp-dev libnotify-bin libnotify-dev avahi-daemon avahi-discover avahi-utils libnss-mdns mdns-scan libwebkit2gtk-4.1-0 libwebkit2gtk-4.1-dev libsoup-3.0-0 libsoup-3.0-dev
|
||||
```
|
||||
- Use `libjsoncpp1` instead of `libjsoncpp25` (for Ubuntu < 22.04)
|
||||
- Arch/Manjaro
|
||||
```bash
|
||||
yay -S mpv libappindicator-gtk3 libsecret jsoncpp libnotify avahi nss-mdns mdns-scan webkit2gtk-4.1 libsoup3
|
||||
```
|
||||
- Fedora
|
||||
```bash
|
||||
dnf install mpv mpv-devel libappindicator-gtk3 libappindicator-gtk3-devel libsecret libsecret-devel jsoncpp jsoncpp-devel libnotify libnotify-devel avahi mdns-scan nss-mdns webkit2gtk4.1 webkit2gtk4.1-devel libsoup3 libsoup3-devel
|
||||
```
|
||||
- Clone the Repo
|
||||
- Create a `.env` in root of the project following the `.env.example` template
|
||||
- Now run the following to bootstrap the project
|
||||
```bash
|
||||
fvm flutter pub get && fvm dart run build_runner build --delete-conflicting-outputs
|
||||
```
|
||||
> 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
|
||||
```bash
|
||||
$ dart create-secrets.dart --local
|
||||
$ flutter run -d <window|macos|linux|(<android-device-id>)>
|
||||
fvm 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 (dev) & we'll review your code
|
||||
|
||||
|
||||
### Submit Translations
|
||||
|
||||
Make sure you're familiar with [Flutter localization](https://docs.flutter.dev/ui/accessibility-and-localization/internationalization). Then, you can start translating the app by following these steps:
|
||||
|
||||
- Do all the steps in [Your First Code Contribution](#your-first-code-contribution)
|
||||
- Make sure application starts in debug mode
|
||||
- Now, in `lib/l10n/app_<2-letter code of your language>.arb` (create if not exists) add necessary translations
|
||||
> (You can follow the `lib/l10n/app_en.arb` for reference)
|
||||
- If you're adding missing translations, you can check the `/untranslated_messages.json` file to see which messages are missing in your native locale
|
||||
- If you added entirely new translations:
|
||||
- Add `const Locale('<2-letter language code>', '<2-letter ISO country code>')` in `lib/l10n/l10n.dart`'s `static final all = [...]` variable
|
||||
- Uncomment the Map entry of your locale from `lib/collections/language_codes.dart`'s `static final Map isoLangs = {` variable
|
||||
- Now restart (hot restart if running already) the app in debug mode & go to "Settings" > "Language" & see if your locale shows up
|
||||
- If it does, select it & see if the app is translated properly
|
||||
- Now git commit the changes & push
|
||||
- Finally, submit a PR against the development branch (dev) & we'll review your code
|
||||
|
2
LICENSE
@ -1,6 +1,6 @@
|
||||
BSD-4-Clause License
|
||||
|
||||
Copyright (c) 2022 Kingkor Roy Tirtho. All rights reserved.
|
||||
Copyright (c) 2025 Kingkor Roy Tirtho. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
|
35
Makefile
@ -1,31 +1,18 @@
|
||||
INNO_VERSION=6.2.0
|
||||
TEMP_DIR=/tmp/spotube-tar
|
||||
USR_SHARE=deb-struct/usr/share
|
||||
BUNDLE_DIR=build/linux/x64/release/bundle
|
||||
BUNDLE_DIR=build/linux/${ARCH}/release/bundle
|
||||
MIRRORLIST=${PWD}/build/mirrorlist
|
||||
deb:
|
||||
mkdir -p ${USR_SHARE}/spotube\
|
||||
&& mkdir -p $(USR_SHARE)/applications $(USR_SHARE)/icons/spotube $(USR_SHARE)/spotube $(USR_SHARE)/appdata\
|
||||
&& cp -r $(BUNDLE_DIR)/* $(USR_SHARE)/spotube\
|
||||
&& cp linux/spotube.desktop $(USR_SHARE)/applications/\
|
||||
&& cp linux/com.github.KRTirtho.Spotube.appdata.xml $(USR_SHARE)/appdata/spotube.appdata.xml\
|
||||
&& cp assets/spotube-logo.png $(USR_SHARE)/icons/spotube\
|
||||
&& sed -i 's|com.github.KRTirtho.Spotube|spotube|' $(USR_SHARE)/appdata/spotube.appdata.xml\
|
||||
&& dpkg-deb -b deb-struct/ build/Spotube-linux-x86_64.deb
|
||||
|
||||
tar:
|
||||
mkdir -p $(TEMP_DIR)\
|
||||
&& cp -r $(BUNDLE_DIR)/* $(TEMP_DIR)\
|
||||
&& cp linux/spotube.desktop $(TEMP_DIR)\
|
||||
&& cp assets/spotube-logo.png $(TEMP_DIR)\
|
||||
&& cp assets/branding/spotube-logo.png $(TEMP_DIR)\
|
||||
&& cp linux/com.github.KRTirtho.Spotube.appdata.xml $(TEMP_DIR)\
|
||||
&& tar -cJf build/Spotube-linux-x86_64.tar.xz -C $(TEMP_DIR) .\
|
||||
&& tar -cJf build/spotube-linux-${VERSION}-${PKG_ARCH}.tar.xz -C $(TEMP_DIR) .\
|
||||
&& rm -rf $(TEMP_DIR)
|
||||
|
||||
appimage:
|
||||
appimage-builder --recipe AppImageBuilder.yml\
|
||||
&& mv Spotube-*-x86_64.AppImage build
|
||||
|
||||
aursrcinfo:
|
||||
docker run -e EXPORT_SRC=1 -v ${PWD}/aur-struct:/pkg -v ${MIRRORLIST}:/etc/pacman.d/mirrorlist:ro whynothugo/makepkg
|
||||
|
||||
@ -41,13 +28,14 @@ publishaur:
|
||||
|
||||
innoinstall:
|
||||
powershell curl -o build\installer.exe http://files.jrsoftware.org/is/6/innosetup-${INNO_VERSION}.exe
|
||||
powershell git clone https://github.com/DomGries/InnoDependencyInstaller.git build\inno-depend
|
||||
powershell build\installer.exe /verysilent /allusers /dir=build\iscc
|
||||
|
||||
inno:
|
||||
powershell .\build\iscc\iscc.exe scripts\windows-setup-creator.iss
|
||||
|
||||
choco:
|
||||
powershell cp dist\**\spotube-*-windows-setup.exe choco-struct\tools
|
||||
powershell cp dist\Spotube-windows-x86_64-setup.exe choco-struct\tools
|
||||
powershell choco pack .\choco-struct\spotube.nuspec --outputdirectory dist
|
||||
|
||||
apk:
|
||||
@ -55,3 +43,16 @@ apk:
|
||||
|
||||
gensums:
|
||||
sh -c scripts/gensums.sh
|
||||
|
||||
migrate:
|
||||
dart run drift_dev make-migrations
|
||||
|
||||
dmg:
|
||||
flutter build macos &&\
|
||||
if [ -f dist/Spotube-macos-universal.dmg ];\
|
||||
then rm dist/Spotube-macos-universal.dmg;\
|
||||
fi &&\
|
||||
appdmg appdmg.json dist/Spotube-macos-universal.dmg
|
||||
|
||||
changelog:
|
||||
git-cliff --unreleased
|
62
PRIVACY_POLICY.md
Normal file
@ -0,0 +1,62 @@
|
||||
**Privacy Policy**
|
||||
|
||||
Kingkor Roy Tirtho built the Spotube app as an Open Source app. This SERVICE is provided by Kingkor Roy Tirtho at no cost and is intended for use as is.
|
||||
|
||||
This page is used to inform visitors regarding my policies with the collection, use, and disclosure of Personal Information if anyone decided to use my Service.
|
||||
|
||||
If you choose to use my Service, then you agree to the collection and use of information in relation to this policy. The Personal Information that I collect is used for providing and improving the Service. I will not use or share your information with anyone except as described in this Privacy Policy.
|
||||
|
||||
The terms used in this Privacy Policy have the same meanings as in our Terms and Conditions, which are accessible at Spotube unless otherwise defined in this Privacy Policy.
|
||||
|
||||
**Information Collection and Use**
|
||||
|
||||
For a better experience, while using our Service, I may require you to provide us with certain personally identifiable information. The information that I request will be retained on your device and is not collected by me in any way.
|
||||
|
||||
The app does use third-party services that may collect information used to identify you.
|
||||
|
||||
Link to the privacy policy of third-party service providers used by the app
|
||||
|
||||
* [Google Play Services](https://www.google.com/policies/privacy/)
|
||||
|
||||
**Log Data**
|
||||
|
||||
Log Data may include information such as your device Internet Protocol (“IP”) address, device name, operating system version, the configuration of the app when utilizing my Service, the time and date of your use of the Service, and other statistics. But none of this info leaves your device. It's stored in a log-file on your device only accessible to you.
|
||||
|
||||
**Cookies**
|
||||
|
||||
Cookies are files with a small amount of data that are commonly used as anonymous unique identifiers. These are sent to your browser from the websites that you visit and are stored on your device's internal memory.
|
||||
|
||||
This Service does not use these “cookies” explicitly. How ever the some services may use cookies for their cause (e.g. improvement) but you can deny them once asked
|
||||
|
||||
**Service Providers**
|
||||
|
||||
I may employ third-party companies and individuals due to the following reasons:
|
||||
|
||||
* To facilitate our Service;
|
||||
* To provide the Service on our behalf;
|
||||
* To perform Service-related services; or
|
||||
* To assist us in analyzing how our Service is used.
|
||||
|
||||
I want to inform users of this Service that these third parties have access to their Personal Information. The reason is to perform the tasks assigned to them on our behalf. However, they are obligated not to disclose or use the information for any other purpose.
|
||||
|
||||
**Security**
|
||||
|
||||
I value your trust in providing us your Personal Information, thus we are striving to use commercially acceptable means of protecting it. But remember that no method of transmission over the internet, or method of electronic storage is 100% secure and reliable, and I cannot guarantee its absolute security.
|
||||
|
||||
**Links to Other Sites**
|
||||
|
||||
This Service may contain links to other sites. If you click on a third-party link, you will be directed to that site. Note that these external sites are not operated by me. Therefore, I strongly advise you to review the Privacy Policy of these websites. I have no control over and assume no responsibility for the content, privacy policies, or practices of any third-party sites or services.
|
||||
|
||||
**Children’s Privacy**
|
||||
|
||||
These Services do not address anyone under the age of 13. I do not knowingly collect personally identifiable information from children under 13 years of age. In the case I discover that a child under 13 has provided me with personal information, I immediately delete this from our servers. If you are a parent or guardian and you are aware that your child has provided us with personal information, please contact me so that I will be able to do the necessary actions.
|
||||
|
||||
**Changes to This Privacy Policy**
|
||||
|
||||
I may update our Privacy Policy from time to time. Thus, you are advised to review this page periodically for any changes. I will notify you of any changes by posting the new Privacy Policy on this page.
|
||||
|
||||
This policy is effective as of 2022-04-01
|
||||
|
||||
**Contact Us**
|
||||
|
||||
If you have any questions or suggestions about my Privacy Policy, do not hesitate to contact me at krtirtho@gmail.com.
|
500
README.md
@ -1,207 +1,337 @@
|
||||

|
||||
<div align="center">
|
||||
<img width="600" src="assets/branding/spotube_banner.png" alt="Spotube Logo">
|
||||
|
||||
<p align="center">
|
||||
<a href="https://github.com/KRTirtho/spotube/actions/workflows/flutter-build.yml">
|
||||
<img alt="GitHub Action Status" src="https://img.shields.io/github/workflow/status/KRTirtho/spotube/Flutter%20Cross%20Build/build?color=%2316ba58&style=flat-square"/>
|
||||
A cross-platform extensible open-source music streaming platform.<br>
|
||||
Bring your own music metadata/playlist with plugins created by community or by yourself. A small step towards the decentralized music streaming era!
|
||||
|
||||
Btw it's not just another Electron app 😉
|
||||
|
||||
<a href="https://spotube.krtirtho.dev"><img alt="Visit the website" height="56" src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/cozy/documentation/website_vector.svg"></a>
|
||||
<a href="https://discord.gg/uJ94vxB6vg"><img alt="Discord Server" height="56" src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/cozy/social/discord-plural_vector.svg"></a>
|
||||
|
||||
<a href="https://patreon.com/krtirtho"><img alt="Support me on Patron" height="56" src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/cozy/donate/patreon-singular_vector.svg"></a>
|
||||
<a href="https://www.buymeacoffee.com/krtirtho"><img alt="Buy me a Coffee" height="56" src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/cozy/donate/buymeacoffee-singular_vector.svg"></a>
|
||||
|
||||
[](https://news.ycombinator.com/item?id=39066136)
|
||||
|
||||
<a href="https://opencollective.com/spotube"><img src="https://opencollective.com/spotube/donate/button.png?color=blue" alt="Donate to our Open Collective" height="45"></a>
|
||||
|
||||
---
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
## 🌃 Features
|
||||
|
||||
- 🧩 Plugin powered, supports any platform or custom music service through plugins.
|
||||
- 🗺️ Community driven plugins for popular platforms or create your own.
|
||||
- ⬇️ Freely downloadable tracks with tagged metadata.
|
||||
- 🖥️ 📱 Cross-platform support.
|
||||
- 🪶 Small size & less data usage.
|
||||
- 🕒 Time synced lyrics regardless of the plugin support.
|
||||
- ✋ No telemetry, diagnostics or user data collection.
|
||||
- 🚀 Native performance.
|
||||
- 📖 Open source/libre software.
|
||||
- 🔉 Playback control is done locally, not on the server.
|
||||
|
||||
## 📜 ⬇️ Installation guide
|
||||
|
||||
New versions usually release every 3-4 months.<br />
|
||||
This handy table lists all the methods you can use to install Spotube:
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<th>Platform</th>
|
||||
<th>Package/Installation Method</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Windows</td>
|
||||
<td>
|
||||
<a href="https://github.com/KRTirtho/spotube/releases/latest/download/Spotube-windows-x86_64-setup.exe">
|
||||
<img width="220" alt="Windows Download" src="https://get.todoist.help/hc/article_attachments/4403191721234/WindowsButton.svg">
|
||||
</a>
|
||||
<a href="https://github.com/KRTirtho/Spotube/releases">
|
||||
<img alt="GitHub release" src="https://img.shields.io/github/v/release/KRTirtho/spotube?color=%2316ba58&style=flat-square"/>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>MacOS</td>
|
||||
<td>
|
||||
<a href="https://github.com/KRTirtho/spotube/releases/latest/download/Spotube-macos-universal.dmg">
|
||||
<img width="220" alt="MacOS Download" src="https://memory-map.com/wp-content/uploads/download-mac-OS-01.svg">
|
||||
</a>
|
||||
<a href="LICENSE">
|
||||
<img alt="License" src="https://img.shields.io/aur/license/spotube-bin?color=%2316ba58&style=flat-square"/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Android</td>
|
||||
<td>
|
||||
<a href="https://github.com/KRTirtho/spotube/releases/latest/download/Spotube-android-all-arch.apk">
|
||||
<img width="220" alt="APK download" src="https://user-images.githubusercontent.com/114044633/223920025-83687de0-e463-4c5d-8122-e06e4bb7d40c.png">
|
||||
</a>
|
||||
<a href="https://github.com/KRTirtho">
|
||||
<img alt="Maintainer" src="https://img.shields.io/badge/Maintainer-KRTirtho-%2316ba58?style=flat-square"/>
|
||||
<br/>
|
||||
<a href="https://f-droid.org/packages/oss.krtirtho.spotube">
|
||||
<img width="220" alt="Download from F-Droid" src="https://user-images.githubusercontent.com/61944859/174589876-bace24c0-b3fd-4c4a-bdb4-6fa82b5853ec.png">
|
||||
</a>
|
||||
<a href="https://opencollective.com/spotube">
|
||||
<img alt="Open Collective backers and sponsors" src="https://img.shields.io/opencollective/all/spotube?color=%2316ba58&style=flat-square"/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<tr>
|
||||
<td>iOS</td>
|
||||
<td>
|
||||
<a href="https://github.com/KRTirtho/spotube/releases/latest/download/Spotube-iOS.ipa">
|
||||
<img width="220" alt="Download iOS IPA" src="https://github.com/user-attachments/assets/3e50d93d-fb39-435c-be6b-337745f7c423">
|
||||
</a>
|
||||
</p>
|
||||
<br/>
|
||||
<blockquote style="color:red">
|
||||
*iPA file only. Requires sideloading with <a href="https://altstore.io/">AltStore</a> or similar tools.
|
||||
</blockquote>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Flatpak</td>
|
||||
<td>
|
||||
<p><code>flatpak install com.github.KRTirtho.Spotube</code></p>
|
||||
<a href="https://flathub.org/apps/details/com.github.KRTirtho.Spotube">
|
||||
<img width="220" alt="Download on Flathub" src="https://flathub.org/assets/badges/flathub-badge-en.png">
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>AppImage</td>
|
||||
<td>AppImage's lacking stability led to it's temporary removal. More information at https://github.com/KRTirtho/spotube/issues/1082</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Debian/Ubuntu</td>
|
||||
<td>
|
||||
<a href="https://github.com/KRTirtho/spotube/releases/latest/download/Spotube-linux-x86_64.deb">
|
||||
<img width="220" alt="Debian/Ubuntu Download" src="https://user-images.githubusercontent.com/61944859/169097994-e92aff78-fd75-4c93-b6e4-f072a4b5a7ed.png">
|
||||
</a>
|
||||
<p>Then run: <code>sudo apt install ./Spotube-linux-x86_64.deb</code></p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Arch/Manjaro</td>
|
||||
<td>
|
||||
<p>With pamac: <code>sudo pamac install spotube-bin</code></p>
|
||||
<p>With yay: <code>yay -Sy spotube-bin</code></p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Fedora/OpenSuse</td>
|
||||
<td>
|
||||
<a href="https://github.com/KRTirtho/spotube/releases/latest/download/Spotube-linux-x86_64.rpm">
|
||||
<img width="220" alt="Fedora/OpenSuse Download" src="https://user-images.githubusercontent.com/61944859/223638350-5926b9da-04d6-4edd-931d-ad533e4ff058.png">
|
||||
</a>
|
||||
<p>For Fedora: <code>sudo dnf install ./Spotube-linux-x86_64.rpm</code></p>
|
||||
<p>For OpenSuse: <code>sudo zypper in ./Spotube-linux-x86_64.rpm</code></p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Linux (tarball)</td>
|
||||
<td>
|
||||
<a href="https://github.com/KRTirtho/spotube/releases/latest">
|
||||
<img width="220" alt="Tarball Download" src="https://user-images.githubusercontent.com/61944859/169456985-e0ba1fd4-10e8-4cc0-ab94-337acc6e0295.png">
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Macos - <a href="https://brew.sh">Homebrew</a></td>
|
||||
<td>
|
||||
<pre lang="bash">
|
||||
brew tap krtirtho/apps
|
||||
brew install --cask spotube
|
||||
</pre>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Windows - <a href="https://chocolatey.org">Chocolatey</a></td>
|
||||
<td>
|
||||
<p><code>choco install spotube</code></p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Windows - <a href="https://scoop.sh">Scoop</a></td>
|
||||
<td>
|
||||
<p><code>scoop bucket add extras</code></p>
|
||||
<p><code>scoop install spotube</code></p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Windows - <a href="https://github.com/microsoft/winget-cli">WinGet</a></td>
|
||||
<td>
|
||||
<p><code>winget install --id KRTirtho.Spotube</code></p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
### 🔄 Nightly Builds
|
||||
|
||||
Spotube is a [Flutter](https://flutter.dev) based lightweight spotify client. It utilizes the power of Spotify & Youtube's public API & creates a hazardless, performant & resource friendly User Experience
|
||||
#### <p align="center">Desktop</p>
|
||||
Grab the latest nightly builds of Spotube [from the GitHub Releases](https://github.com/KRTirtho/spotube/releases/tag/nightly).
|
||||
|
||||

|
||||
## 🕳️ Building from source
|
||||
|
||||
#### <p align="center">Mobile</p>
|
||||
<a href="https://github.com/KRTirtho/spotube/actions"><img alt="GitHub Workflow Status" src="https://img.shields.io/github/actions/workflow/status/KRTirtho/spotube/spotube-release-binary.yml?+label=Build%20Status"></a>
|
||||
|
||||

|
||||
You can compile Spotube's source code by [following these instructions](CONTRIBUTION.md#your-first-code-contribution).
|
||||
|
||||
# Features
|
||||
## 👥 The Spotube team
|
||||
|
||||
Following are the features that currently spotube offers:
|
||||
- [Kingkor Roy Tirtho](https://github.com/KRTirtho) - The Founder, Maintainer and Lead Developer
|
||||
- [Owen Connor](https://github.com/owencz1998) - The Cool Discord Moderator
|
||||
- [Piotr Rogowski](https://github.com/karniv00l) - The MacOS Developer
|
||||
- [Rusty Apple](https://github.com/RustyApple) - The Mysterious Unknown Guy
|
||||
|
||||
- Open Source
|
||||
- Anonymous/Guest Login
|
||||
- Cross platform
|
||||
- No telemetry, diagnostics or user data collection
|
||||
- Lightweight & resource friendly
|
||||
- Native performance (Thanks to Flutter+Skia)
|
||||
- Playback control is on user's machine instead of server based
|
||||
- Small size & less data hungry
|
||||
- No spotify or youtube ads since it uses all public & free APIs (But it's recommended to support the creators by watching/liking/subscribing to the artists youtube channel or add as favourite track in spotify. Mostly buying spotify premium is the best way to support their valuable creations)
|
||||
- Lyrics
|
||||
- Downloadable track
|
||||
## 💼 License
|
||||
|
||||
<a href="https://www.producthunt.com/posts/spotube?utm_source=badge-featured&utm_medium=badge&utm_souce=badge-spotube" target="_blank"><img src="https://api.producthunt.com/widgets/embed-image/v1/featured.svg?post_id=327965&theme=dark" alt="Spotube - A lightweight+free Spotify crossplatform-client made with flutter | Product Hunt" style="width: 250px; height: 54px;" width="250" height="54" /></a>
|
||||
Spotube is open source and licensed under the [BSD-4-Clause](/LICENSE) License.
|
||||
|
||||
# Installation
|
||||
|
||||
I'm always releasing newer versions of binary of the software each 2-3 month with minor changes & each 6-8 month with major changes. Grab the binaries
|
||||
|
||||
All the binaries are located in the [releases](https://github.com/krtirtho/spotube/releases), just download
|
||||
|
||||
## Android
|
||||
|
||||
Download the [Android app](https://github.com/KRTirtho/spotube/releases/latest/download/Spotube-android-all-arch.apk) & then install it on your Android smartphone/tablet
|
||||
|
||||
## Windows
|
||||
|
||||
Download the [setup file](https://github.com/KRTirtho/spotube/releases/latest/download/Spotube-windows-x86_64-setup.exe) & follow along the installer
|
||||
|
||||
### Chocolatey
|
||||
|
||||
Run the following command to install Spotube with windows chocolatey package manager
|
||||
```powershell
|
||||
choco install spotube
|
||||
```
|
||||
|
||||
### Winget
|
||||
Run the following command to install Spotube with new Windows Package Manager:
|
||||
```powershell
|
||||
winget install --id KRTirtho.Spotube
|
||||
```
|
||||
|
||||
## Linux
|
||||
|
||||
### Flatpak
|
||||
Run in terminal:
|
||||
```shell
|
||||
$ flatpak install flathub com.github.KRTirtho.Spotube
|
||||
```
|
||||
<a href='https://flathub.org/apps/details/com.github.KRTirtho.Spotube'><img width='240' alt='Download on Flathub' src='https://flathub.org/assets/badges/flathub-badge-en.png'/></a>
|
||||
|
||||
### Ubuntu/Debian/Linux Mint/Pop_!OS:
|
||||
Download the [Spotube-linux-x86_64.deb](https://github.com/KRTirtho/spotube/releases/latest/download/Spotube-linux-x86_64.deb) then double click it or run
|
||||
```bash
|
||||
$ sudo apt install Spotube-linux-x86_64.deb
|
||||
# or
|
||||
$ sudo dpkg -i Spotube-linux-x86_64.deb
|
||||
```
|
||||
in the directory where it was downloaded
|
||||
|
||||
|
||||
### Arch/Manjaro/Endeavour:
|
||||
Run following terminal
|
||||
```bash
|
||||
# for `yay` users
|
||||
$ yay -S spotube-bin
|
||||
# for `pamac` users
|
||||
$ pamac install spotube-bin
|
||||
```
|
||||
|
||||
|
||||
### AppImage:
|
||||
Download the [Spotube-linux-x86_64.AppImage](https://github.com/KRTirtho/spotube/releases/latest/download/Spotube-linux-x86_64.AppImage) file & double click to run it. AppImages require [appimage-launcher](https://github.com/TheAssassin/AppImageLauncher) to be installed
|
||||
|
||||
## Mac OS
|
||||
Download the [Mac OS Disk Image (.dmg) file](https://github.com/KRTirtho/spotube/releases/latest/download/Spotube-macos-x86_64.dmg) from the release & follow along the setup wizard
|
||||
|
||||
## Nightly Builds
|
||||
Get the latest nightly builds of Spotube [here](https://nightly.link/KRTirtho/spotube/workflows/flutter-build/build)
|
||||
|
||||
## Optional Configurations
|
||||
<details>
|
||||
<summary>Login with <b>Spotify</b></summary>
|
||||
|
||||
You need a spotify account & a developer app for
|
||||
|
||||
- clientId
|
||||
- clientSecret
|
||||
|
||||
**Grab credentials:**
|
||||
|
||||
- Go to https://developer.spotify.com/dashboard/login & login with your spotify account (Skip if you're logged in)
|
||||

|
||||
|
||||
- Create an web app for Spotify Public API
|
||||

|
||||
|
||||
- Give the app a name & description. Then Edit settings & add **http://localhost:4304/auth/spotify/callback** as **Redirect URI** for the app. Its important for authenticating
|
||||

|
||||
|
||||
- Click on **SHOW CLIENT SECRET** to reveal the **clientSecret**. Then copy the **clientID**, **clientSecret** & paste in the **Spotube's** respective fields
|
||||

|
||||
</details>
|
||||
If you are curious, you can [read the reason of choosing this license](https://dev.to/krtirtho/choosing-open-source-license-wisely-1m3p).
|
||||
|
||||
<details>
|
||||
<summary>Setup <b>Genius Lyrics</b></summary>
|
||||
<summary>
|
||||
<h2><code>[Click to show]</code> 🙏 Services/Package/Plugin Credits</h2>
|
||||
</summary>
|
||||
|
||||
- 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
|
||||

|
||||
- Generate & copy access token
|
||||

|
||||
- Paste the copied access token in Spotube's Settings
|
||||

|
||||
### Services
|
||||
|
||||
> **Note!**: No personal data or any kind of sensitive information won't be collected from spotify. Don't believe? See the code for yourself
|
||||
1. [Flutter](https://flutter.dev) - Flutter transforms the app development process. Build, test, and deploy beautiful mobile, web, desktop, and embedded apps from a single codebase
|
||||
1. [MPV](https://mpv.io) - mpv is a free (as in freedom) media player for the command line. It supports a wide variety of media file formats, audio and video codecs, and subtitle types.
|
||||
1. [Musicbrainz](https://musicbrainz.org) - MusicBrainz is a MetaBrainz project that aims to create a collaborative music database that is similar to the freedb project.
|
||||
1. [Listenbrainz](https://listenbrainz.org) - ListenBrainz is a open-source project by the MetaBrainz Foundation that allows users to crowdsource and publicly store their digital music listening data.
|
||||
1. [Piped](https://piped-docs.kavin.rocks/) - Piped is a privacy friendly alternative YouTube frontend, which is efficient and scalable by design.
|
||||
1. [Invidious](https://invidious.io/) - Invidious is an open source alternative front-end to YouTube.
|
||||
1. [yt-dlp](https://github.com/yt-dlp/yt-dlp) - A feature-rich command-line audio/video downloader.
|
||||
1. [NewPipeExtractor](https://github.com/TeamNewPipe/NewPipeExtractor) - NewPipe's core library for extracting data from streaming sites.
|
||||
1. [SongLink](https://song.link) - SongLink is a free smart link service that helps you share music with your audience. It's a one-stop-shop for creating smart links for music, podcasts, and other audio content
|
||||
1. [LRCLib](https://lrclib.net/) - A public synced lyric API.
|
||||
1. [Linux](https://www.linux.org) - Linux is a family of open-source Unix-like operating systems based on the Linux kernel, an operating system kernel first released on September 17, 1991, by Linus Torvalds. Linux is typically packaged in a Linux distribution
|
||||
1. [AUR](https://aur.archlinux.org) - AUR stands for Arch User Repository. It is a community-driven repository for Arch-based Linux distributions users
|
||||
1. [Flatpak](https://flatpak.org) - Flatpak is a utility for software deployment and package management for Linux
|
||||
1. [SponsorBlock](https://sponsor.ajay.app) - SponsorBlock is an open-source crowdsourced browser extension and open API for skipping sponsor segments in YouTube videos.
|
||||
1. [Inno Setup](https://jrsoftware.org/isinfo.php) - Inno Setup is a free installer for Windows programs by Jordan Russell and Martijn Laan
|
||||
1. [F-Droid](https://f-droid.org) - F-Droid is an installable catalogue of FOSS (Free and Open Source Software) applications for the Android platform. The client makes it easy to browse, install, and keep track of updates on your device
|
||||
1. [LastFM](https://last.fm) - Last.fm is a music streaming and discovery platform that helps users discover and share new music. It tracks users' music listening habits across many devices and platforms.
|
||||
|
||||
### Dependencies
|
||||
|
||||
1. [app_links](https://github.com/llfbandit/app_links) - Android App Links, Deep Links, iOs Universal Links and Custom URL schemes handler for Flutter (desktop included).
|
||||
1. [args](https://pub.dev/packages/args) - Library for defining parsers for parsing raw command-line arguments into a set of options and values using GNU and POSIX style options.
|
||||
1. [async](https://pub.dev/packages/async) - Utility functions and classes related to the 'dart:async' library.
|
||||
1. [audio_service](https://pub.dev/packages/audio_service) - Flutter plugin to play audio in the background while the screen is off.
|
||||
1. [audio_service_mpris](https://github.com/bdrazhzhov/audio-service-mpris) - audio_service platform interface supporting Media Player Remote Interfacing Specification.
|
||||
1. [audio_session](https://github.com/ryanheise/audio_session) - Sets the iOS audio session category and Android audio attributes for your app, and manages your app's audio focus, mixing and ducking behaviour.
|
||||
1. [auto_route](https://github.com/Milad-Akarie/auto_route_library) - AutoRoute is a declarative routing solution, where everything needed for navigation is automatically generated for you.
|
||||
1. [auto_size_text](https://github.com/leisim/auto_size_text) - Flutter widget that automatically resizes text to fit perfectly within its bounds.
|
||||
1. [bonsoir](https://bonsoir.skyost.eu) - A Zeroconf library that allows you to discover network services and to broadcast your own. Based on Apple Bonjour and Android NSD.
|
||||
1. [cached_network_image](https://github.com/Baseflow/flutter_cached_network_image) - Flutter library to load and cache network images. Can also be used with placeholder and error widgets.
|
||||
1. [connectivity_plus](https://github.com/fluttercommunity/plus_plugins) - Flutter plugin for discovering the state of the network (WiFi & mobile/cellular) connectivity on Android and iOS.
|
||||
1. [device_info_plus](https://github.com/fluttercommunity/plus_plugins) - Flutter plugin providing detailed information about the device (make, model, etc.), and Android or iOS version the app is running on.
|
||||
1. [dio](https://github.com/cfug/dio) - A powerful HTTP networking package,supports Interceptors,Aborting and canceling a request,Custom adapters, Transformers, etc.
|
||||
1. [drift](https://drift.simonbinder.eu/) - Drift is a reactive library to store relational data in Dart and Flutter applications.
|
||||
1. [duration](https://github.com/desktop-dart/duration) - Utilities to make working with 'Duration's easier. Formats duration in human readable form and also parses duration in human readable form to Dart's Duration.
|
||||
1. [encrypt](https://pub.dev/packages/encrypt) - A set of high-level APIs over PointyCastle for two-way cryptography.
|
||||
1. [envied](https://github.com/petercinibulk/envied) - Explicitly reads environment variables into a dart file from a .env file for more security and faster start up times.
|
||||
1. [file_picker](https://github.com/miguelpruivo/plugins_flutter_file_picker) - A package that allows you to use a native file explorer to pick single or multiple absolute file paths, with extension filtering support.
|
||||
1. [file_selector](https://pub.dev/packages/file_selector) - Flutter plugin for opening and saving files, or selecting directories, using native file selection UI.
|
||||
1. [fluentui_system_icons](https://github.com/microsoft/fluentui-system-icons/tree/main) - Fluent UI System Icons are a collection of familiar, friendly and modern icons from Microsoft.
|
||||
1. [flutter_cache_manager](https://github.com/Baseflow/flutter_cache_manager/tree/develop/flutter_cache_manager) - Generic cache manager for flutter. Saves web files on the storages of the device and saves the cache info using sqflite.
|
||||
1. [flutter_discord_rpc](https://pub.dev/packages/flutter_discord_rpc) - Discord RPC support for Flutter desktop platforms
|
||||
1. [flutter_displaymode](https://github.com/ajinasokan/flutter_displaymode) - A Flutter plugin to set display mode (resolution, refresh rate) on Android platform. Allows to enable high refresh rate on supported devices.
|
||||
1. [flutter_feather_icons](https://github.com/muj-programmer/flutter_feather_icons) - Feather is a collection of simply beautiful open source icons. Each icon is designed on a 24x24 grid with an emphasis on simplicity, consistency and usability.
|
||||
1. [flutter_form_builder](https://github.com/flutter-form-builder-ecosystem) - This package helps in creation of forms in Flutter by removing the boilerplate code, reusing validation, react to changes, and collect final user input.
|
||||
1. [flutter_hooks](https://github.com/rrousselGit/flutter_hooks) - A flutter implementation of React hooks. It adds a new kind of widget with enhanced code reuse.
|
||||
1. [flutter_inappwebview](https://inappwebview.dev/) - A Flutter plugin that allows you to add an inline webview, to use an headless webview, and to open an in-app browser window.
|
||||
1. [flutter_native_splash](https://pub.dev/packages/flutter_native_splash) - Customize Flutter's default white native splash screen with background color and splash image. Supports dark mode, full screen, and more.
|
||||
1. [flutter_riverpod](https://riverpod.dev) - A reactive caching and data-binding framework. Riverpod makes working with asynchronous code a breeze.
|
||||
1. [flutter_secure_storage](https://pub.dev/packages/flutter_secure_storage) - Flutter Secure Storage provides API to store data in secure storage. Keychain is used in iOS, KeyStore based solution is used in Android.
|
||||
1. [flutter_sharing_intent](https://github.com/bhagat-techind/flutter_sharing_intent.git) - A flutter plugin that allow flutter apps to receive photos, videos, text, urls or any other file types from another app.
|
||||
1. [flutter_undraw](https://github.com/KRTirtho/flutter_undraw) - Undraw.co Illustrations for Flutter with customization options
|
||||
1. [form_builder_validators](https://github.com/flutter-form-builder-ecosystem) - Form Builder Validators set of validators for FlutterFormBuilder. Provides common validators and a way to make your own.
|
||||
1. [form_validator](https://github.com/TheMisir/form-validator) - Simplest form validation library for flutter's form field widgets
|
||||
1. [freezed_annotation](https://pub.dev/packages/freezed_annotation) - Annotations for the freezed code-generator. This package does nothing without freezed too.
|
||||
1. [fuzzywuzzy](https://github.com/sphericalkat/dart-fuzzywuzzy) - An implementation of the popular fuzzywuzzy package in Dart, to suit all your fuzzy string matching/searching needs!
|
||||
1. [gap](https://github.com/letsar/gap) - Flutter widgets for easily adding gaps inside Flex widgets such as Columns and Rows or scrolling views.
|
||||
1. [google_fonts](https://pub.dev/packages/google_fonts) - A Flutter package to use fonts from fonts.google.com. Supports HTTP fetching, caching, and asset bundling.
|
||||
1. [home_widget](https://pub.dev/packages/home_widget) - A plugin to provide a common interface for creating HomeScreen Widgets for Android and iOS.
|
||||
1. [hooks_riverpod](https://riverpod.dev) - A reactive caching and data-binding framework. Riverpod makes working with asynchronous code a breeze.
|
||||
1. [html](https://pub.dev/packages/html) - APIs for parsing and manipulating HTML content outside the browser.
|
||||
1. [html_unescape](https://github.com/filiph/html_unescape) - A small library for un-escaping HTML. Supports all Named Character References, Decimal Character References and Hexadecimal Character References.
|
||||
1. [http](https://pub.dev/packages/http) - A composable, multi-platform, Future-based API for HTTP requests.
|
||||
1. [image_picker](https://pub.dev/packages/image_picker) - Flutter plugin for selecting images from the Android and iOS image library, and taking new pictures with the camera.
|
||||
1. [intl](https://pub.dev/packages/intl) - Contains code to deal with internationalized/localized messages, date and number formatting and parsing, bi-directional text, and other internationalization issues.
|
||||
1. [invidious](https://pub.dev/packages/invidious) - Invidious API client for Dart and Flutter.
|
||||
1. [jiosaavn](https://github.com/KRTirtho/jiosaavn) - Unofficial API client for jiosaavn.com
|
||||
1. [json_annotation](https://pub.dev/packages/json_annotation) - Classes and helper functions that support JSON code generation via the `json_serializable` package.
|
||||
1. [local_notifier](https://github.com/leanflutter/local_notifier) - This plugin allows Flutter desktop apps to displaying local notifications.
|
||||
1. [logger](https://pub.dev/packages/logger) - Small, easy to use and extensible logger which prints beautiful logs.
|
||||
1. [logging](https://pub.dev/packages/logging) - Provides APIs for debugging and error logging, similar to loggers in other languages, such as the Closure JS Logger and java.util.logging.Logger.
|
||||
1. [lrc](https://pub.dev/packages/lrc) - A Dart-only package that creates, parses, and handles LRC, which is a format that stores song lyrics.
|
||||
1. [media_kit](https://github.com/media-kit/media-kit) - A cross-platform video player & audio player for Flutter & Dart. Performant, stable, feature-proof & modular.
|
||||
1. [media_kit_libs_audio](https://github.com/media-kit/media-kit.git) - package:media_kit audio (only) playback native libraries for all platforms.
|
||||
1. [metadata_god](https://pub.dev/packages/metadata_god) - Plugin for retrieving and writing audio tags/metadata from audio files
|
||||
1. [mime](https://pub.dev/packages/mime) - Utilities for handling media (MIME) types, including determining a type from a file extension and file contents.
|
||||
1. [open_file](https://pub.dev/packages/open_file) - A plug-in that can call native APP to open files with string result in flutter, support iOS(UTI) / android(intent) / PC(ffi) / web(dart:html)
|
||||
1. [package_info_plus](https://github.com/fluttercommunity/plus_plugins) - Flutter plugin for querying information about the application package, such as CFBundleVersion on iOS or versionCode on Android.
|
||||
1. [palette_generator](https://pub.dev/packages/palette_generator) - Flutter package for generating palette colors from a source image.
|
||||
1. [path](https://pub.dev/packages/path) - A string-based path manipulation library. All of the path operations you know and love, with solid support for Windows, POSIX (Linux and Mac OS X), and the web.
|
||||
1. [path_provider](https://pub.dev/packages/path_provider) - Flutter plugin for getting commonly used locations on host platform file systems, such as the temp and app data directories.
|
||||
1. [permission_handler](https://pub.dev/packages/permission_handler) - Permission plugin for Flutter. This plugin provides a cross-platform (iOS, Android) API to request and check permissions.
|
||||
1. [piped_client](https://github.com/KRTirtho/piped_client) - API Client for piped.video
|
||||
1. [riverpod](https://riverpod.dev) - A reactive caching and data-binding framework. Riverpod makes working with asynchronous code a breeze.
|
||||
1. [scroll_to_index](https://github.com/quire-io/scroll-to-index) - Scroll to a specific child of any scrollable widget in Flutter
|
||||
1. [shadcn_flutter](https://github.com/sunarya-thito/shadcn_flutter) - Beautifully designed components from Shadcn/UI is now available for Flutter
|
||||
1. [shared_preferences](https://pub.dev/packages/shared_preferences) - Flutter plugin for reading and writing simple key-value pairs. Wraps NSUserDefaults on iOS and SharedPreferences on Android.
|
||||
1. [shelf](https://pub.dev/packages/shelf) - A model for web server middleware that encourages composition and easy reuse.
|
||||
1. [shelf_router](https://pub.dev/packages/shelf_router) - A convenient request router for the shelf web-framework, with support for URL-parameters, nested routers and routers generated from source annotations.
|
||||
1. [shelf_web_socket](https://pub.dev/packages/shelf_web_socket) - A shelf handler that wires up a listener for every connection.
|
||||
1. [simple_icons](https://teavelopment.com/) - The Simple Icon pack available as Flutter Icons. Provides over 1500 Free SVG icons for popular brands.
|
||||
1. [skeletonizer](https://github.com/Milad-Akarie/skeletonizer) - Converts already built widgets into skeleton loaders with no extra effort.
|
||||
1. [sliding_up_panel](https://github.com/akshathjain/sliding_up_panel) - A draggable Flutter widget that makes implementing a SlidingUpPanel much easier!
|
||||
1. [sliver_tools](https://github.com/Kavantix) - A set of useful sliver tools that are missing from the flutter framework
|
||||
1. [smtc_windows](https://pub.dev/packages/smtc_windows) - Windows `SystemMediaTransportControls` implementation for Flutter giving access to Windows OS Media Control applet.
|
||||
1. [sqlite3](https://github.com/simolus3/sqlite3.dart/tree/main/sqlite3) - Provides lightweight yet convenient bindings to SQLite by using dart:ffi
|
||||
1. [sqlite3_flutter_libs](https://github.com/simolus3/sqlite3.dart/tree/main/sqlite3_flutter_libs) - Flutter plugin to include native sqlite3 libraries with your app
|
||||
1. [stroke_text](https://github.com/MohamedAbd0/stroke_text) - A Simple Flutter plugin for applying stroke (border) style to a text widget
|
||||
1. [system_theme](https://github.com/bdlukaa/system_theme/tree/master/system_theme) - A plugin to get the current system theme info. Supports Android, Web, Windows, Linux and macOS
|
||||
1. [test](https://pub.dev/packages/test) - A full featured library for writing and running Dart tests across platforms.
|
||||
1. [timezone](https://pub.dev/packages/timezone) - Time zone database and time zone aware DateTime.
|
||||
1. [titlebar_buttons](https://github.com/gtk-flutter/titlebar_buttons) - A package which provides most of the titlebar buttons from windows, linux and macos.
|
||||
1. [tray_manager](https://github.com/leanflutter/tray_manager) - This plugin allows Flutter desktop apps to defines system tray.
|
||||
1. [url_launcher](https://pub.dev/packages/url_launcher) - Flutter plugin for launching a URL. Supports web, phone, SMS, and email schemes.
|
||||
1. [uuid](https://pub.dev/packages/uuid) - RFC4122 (v1, v4, v5, v6, v7, v8) UUID Generator and Parser for Dart
|
||||
1. [version](https://github.com/dartninja/version) - Provides a simple class for parsing and comparing semantic versions as defined by http://semver.org/
|
||||
1. [very_good_infinite_list](https://github.com/VeryGoodOpenSource/very_good_infinite_list) - A library for easily displaying paginated data, created by Very Good Ventures. Great for activity feeds, news feeds, and more.
|
||||
1. [visibility_detector](https://pub.dev/packages/visibility_detector) - A widget that detects the visibility of its child and notifies a callback.
|
||||
1. [web_socket_channel](https://pub.dev/packages/web_socket_channel) - StreamChannel wrappers for WebSockets. Provides a cross-platform WebSocketChannel API, a cross-platform implementation of that API that communicates over an underlying StreamChannel.
|
||||
1. [wikipedia_api](https://github.com/KRTirtho/wikipedia_api) - Wikipedia API for dart and flutter
|
||||
1. [win32_registry](https://pub.dev/packages/win32_registry) - A package that provides a friendly Dart API for accessing the Windows Registry.
|
||||
1. [window_manager](https://github.com/leanflutter/window_manager) - This plugin allows Flutter desktop apps to resizing and repositioning the window.
|
||||
1. [youtube_explode_dart](https://github.com/Hexer10/youtube_explode_dart) - A port in dart of the youtube explode library. Supports several API functions without the need of Youtube API Key.
|
||||
1. [http_parser](https://pub.dev/packages/http_parser) - A platform-independent package for parsing and serializing HTTP formats.
|
||||
1. [collection](https://pub.dev/packages/collection) - Collections and utilities functions and classes related to collections.
|
||||
1. [otp_util](https://github.com/dushiling) - otp_util is a dart package to generate and verify one-time passwords,it It provides two methods TOPT and HOTP.They are Time-based OTPs and Counter-based OTPs.
|
||||
1. [dio_http2_adapter](https://github.com/cfug/dio) - An adapter that combines HTTP/2 and dio. Supports reusing connections, header compression, etc.
|
||||
1. [build_runner](https://pub.dev/packages/build_runner) - A build system for Dart code generation and modular compilation.
|
||||
1. [envied_generator](https://github.com/petercinibulk/envied) - Generator for the Envied package. See https://pub.dev/packages/envied.
|
||||
1. [flutter_gen_runner](https://github.com/FlutterGen/flutter_gen) - The Flutter code generator for your assets, fonts, colors, … — Get rid of all String-based APIs.
|
||||
1. [flutter_launcher_icons](https://github.com/fluttercommunity/flutter_launcher_icons) - A package which simplifies the task of updating your Flutter app's launcher icon.
|
||||
1. [flutter_lints](https://pub.dev/packages/flutter_lints) - Recommended lints for Flutter apps, packages, and plugins to encourage good coding practices.
|
||||
1. [json_serializable](https://pub.dev/packages/json_serializable) - Automatically generate code for converting to and from JSON by annotating Dart classes.
|
||||
1. [freezed](https://pub.dev/packages/freezed) - Code generation for immutable classes that has a simple syntax/API without compromising on the features.
|
||||
1. [process_run](https://github.com/tekartik/process_run.dart/blob/master/packages/process_run) - Process run helpers for Linux/Win/Mac and which like feature for finding executables.
|
||||
1. [pubspec_parse](https://pub.dev/packages/pubspec_parse) - Simple package for parsing pubspec.yaml files with a type-safe API and rich error reporting.
|
||||
1. [pub_api_client](https://github.com/leoafarias/pub_api_client) - An API Client for Pub to interact with public package information.
|
||||
1. [xml](https://github.com/renggli/dart-xml) - A lightweight library for parsing, traversing, querying, transforming and building XML documents.
|
||||
1. [io](https://pub.dev/packages/io) - Utilities for the Dart VM Runtime including support for ANSI colors, file copying, and standard exit code values.
|
||||
1. [drift_dev](https://drift.simonbinder.eu/) - Dev-dependency for users of drift. Contains the generator and development tools.
|
||||
1. [auto_route_generator](https://github.com/Milad-Akarie/auto_route_library) - AutoRoute is a declarative routing solution, where everything needed for navigation is automatically generated for you.
|
||||
1. [desktop_webview_window](https://github.com/MixinNetwork/flutter-plugins/tree/main/packages/desktop_webview_window) - Show a webview window on your flutter desktop application.
|
||||
1. [disable_battery_optimization](https://github.com/pvsvamsi/Disable-Battery-Optimizations) - Flutter plugin to check and disable battery optimizations. Also shows custom steps to disable the optimizations in devices like mi, xiaomi, samsung, oppo, huawei, oneplus etc
|
||||
1. [draggable_scrollbar](https://github.com/fluttercommunity/flutter-draggable-scrollbar) - A scrollbar that can be dragged for quickly navigation through a vertical list. Additional option is showing label next to scrollthumb with information about current item.
|
||||
1. [flutter_broadcasts](https://github.com/KRTirtho/flutter_broadcasts.git) - A plugin for sending and receiving broadcasts with Android intents and iOS notifications.
|
||||
1. [scrobblenaut](https://github.com/Nebulino/Scrobblenaut) - A deadly simple LastFM API Wrapper for Dart. So deadly simple that it's gonna hit the mark.
|
||||
1. [yt_dlp_dart](https://github.com/KRTirtho/yt_dlp_dart.git) - yt-dlp binding in Dart
|
||||
1. [flutter_new_pipe_extractor](https://github.com/KRTirtho/flutter_new_pipe_extractor) - NewPipeExtractor binding for Flutter (Android only)
|
||||
</details>
|
||||
|
||||
# TODO:
|
||||
|
||||
- [x] Compile, Debug & Build for **MacOS**
|
||||
- [x] Add support for show Lyric of currently playing track
|
||||
- [x] Track download
|
||||
- [ ] Support for playing/streaming podcasts/shows
|
||||
- [x] Artist, User & Album pages
|
||||
- [x] Android Support
|
||||
|
||||
# Building from source
|
||||
|
||||
You can find the details [here](CONTRIBUTION.md#your-first-code-contribution)
|
||||
|
||||
# Things that don't work
|
||||
|
||||
- Shows & Podcasts aren't supported as it'd require premium anyway
|
||||
- OS Media Controls
|
||||
|
||||
# License
|
||||
|
||||
[BSD-4-Clause](/LICENSE)
|
||||
|
||||
Bu why? You can learn about it [here](https://dev.to/krtirtho/choosing-open-source-license-wisely-1m3p)
|
||||
|
||||
# Relevant Project/Tools Links
|
||||
|
||||
- [Flutter](https://flutter.dev/) - Flutter transforms the app development process. Build, test, and deploy beautiful mobile, web, desktop, and embedded apps from a single codebase
|
||||
- [Linux](https://www.linux.org/) - Linux is a family of open-source Unix-like operating systems based on the Linux kernel, an operating system kernel first released on September 17, 1991, by Linus Torvalds. Linux is typically packaged in a Linux distribution
|
||||
- [AUR](https://aur.archlinux.org/) - AUR stands for Arch User Repository. It is a community-driven repository for Arch-based Linux distributions users
|
||||
- [Flatpak](https://flatpak.org/) - Flatpak is a utility for software deployment and package management for Linux
|
||||
- [spotify (dart)](https://github.com/rinukkusu/spotify-dart) - A dart library for interfacing with the Spotify API
|
||||
- [just_audio](https://github.com/ryanheise/just_audio/tree/master/just_audio) - A feature-rich cross-platform audio player for Flutter that supports network audio streams too
|
||||
- [libwinmedia](https://github.com/harmonoid/libwinmedia) - A cross-platform media playback library for C/C++ with good number of features (only Windows & Linux)
|
||||
- [youtube_explode_dart](https://github.com/Hexer10/youtube_explode_dart) - YoutubeExplode is a library that provides an interface to query metadata of YouTube videos, playlists and channels, as well as to resolve and download video streams and closed caption tracks
|
||||
- [infinite_scroll_pagination](https://github.com/EdsonBueno/infinite_scroll_pagination) - Flutter package to help you lazily load and display pages of items as the user scrolls down your screen
|
||||
- [bitsdojo_window](https://github.com/bitsdojo/bitsdojo_window) - A Flutter package that makes it easy to customize and work with your Flutter desktop app window on Windows, macOS and Linux
|
||||
- [hotkey_manager](https://github.com/leanflutter/hotkey_manager) - A flutter plugin that allow Flutter desktop apps to defines system/inapp wide hotkey
|
||||
- [Inno Setup](https://jrsoftware.org/isinfo.php) - Inno Setup is a free installer for Windows programs by Jordan Russell and Martijn Laan
|
||||
- [collection](https://github.com/dart-lang/collection) - The collection package for Dart contains a number of separate libraries with utility functions and classes that makes working with collections easier
|
||||
- [flutter_riverpod](https://riverpod.dev/) - A Reactive Caching and Data-binding Framework
|
||||
- [flutter_hooks](https://github.com/rrousselGit/flutter_hooks) - React hooks for Flutter. Hooks are a new kind of object that manages a Widget life-cycles. They are used to increase code sharing between widgets and as a complete replacement for StatefulWidget
|
||||
- [hooks_riverpod](https://riverpod.dev/) - Riverpod with hooks
|
||||
- [go_router](https://github.com/flutter/packages/tree/main/packages/go_router) - A declarative router for Flutter based on Navigation 2 supporting deep linking, data-driven routes and more
|
||||
- [palette_generator](https://github.com/flutter/packages/tree/main/packages/palette_generator) - Flutter package for generating palette colors from a source image.
|
||||
- [audio_session](https://github.com/ryanheise/audio_session) - Sets the iOS audio session category and Android audio attributes for your app, and manages your app's audio focus, mixing and ducking behaviour.
|
||||
- [logger](https://github.com/leisim/logger) - Small, easy to use and extensible logger which prints beautiful logs
|
||||
- [flutter_launcher_icons](https://github.com/fluttercommunity/flutter_launcher_icons) - A package which simplifies the task of updating your Flutter app's launcher icon.
|
||||
- [permission_handler](https://github.com/baseflow/flutter-permission-handler) - Permission plugin for Flutter. This plugin provides a cross-platform (iOS, Android) API to request and check permissions.
|
||||
|
||||
|
||||
# Social handlers
|
||||
|
||||
Follow me on [Twitter](https://twitter.com/@krtirtho) for newer updates about this application
|
||||
|
||||
|
||||
<p align="center">© 2022 Spotube</p>
|
||||
<div align="center"><h4>© Copyright Spotube 2025</h4></div>
|
||||
|
@ -25,6 +25,16 @@ linter:
|
||||
# avoid_print: false # Uncomment to disable the `avoid_print` rule
|
||||
# prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
|
||||
file_names: false
|
||||
avoid_renaming_method_parameters: false
|
||||
|
||||
# Additional information about this file can be found at
|
||||
# https://dart.dev/guides/language/analysis-options
|
||||
analyzer:
|
||||
errors:
|
||||
invalid_annotation_target: ignore
|
||||
exclude:
|
||||
- "**.freezed.dart"
|
||||
- "**.g.dart"
|
||||
- "**.gr.dart"
|
||||
- "**/generated_plugin_registrant.dart"
|
||||
- test/**/*.dart
|
||||
|
@ -1,3 +1,9 @@
|
||||
plugins {
|
||||
id "com.android.application"
|
||||
id "kotlin-android"
|
||||
id "dev.flutter.flutter-gradle-plugin"
|
||||
}
|
||||
|
||||
def localProperties = new Properties()
|
||||
def localPropertiesFile = rootProject.file('local.properties')
|
||||
if (localPropertiesFile.exists()) {
|
||||
@ -6,11 +12,6 @@ if (localPropertiesFile.exists()) {
|
||||
}
|
||||
}
|
||||
|
||||
def flutterRoot = localProperties.getProperty('flutter.sdk')
|
||||
if (flutterRoot == null) {
|
||||
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
|
||||
}
|
||||
|
||||
def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
|
||||
if (flutterVersionCode == null) {
|
||||
flutterVersionCode = '1'
|
||||
@ -21,14 +22,23 @@ if (flutterVersionName == null) {
|
||||
flutterVersionName = '1.0'
|
||||
}
|
||||
|
||||
apply plugin: 'com.android.application'
|
||||
apply plugin: 'kotlin-android'
|
||||
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
|
||||
def keystoreProperties = new Properties()
|
||||
def keystorePropertiesFile = rootProject.file('key.properties')
|
||||
if (keystorePropertiesFile.exists()) {
|
||||
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
|
||||
}
|
||||
|
||||
def composeVersion = "1.4.8"
|
||||
|
||||
android {
|
||||
compileSdkVersion 31
|
||||
namespace "oss.krtirtho.spotube"
|
||||
|
||||
compileSdkVersion 36
|
||||
|
||||
ndkVersion = "27.0.12077973"
|
||||
|
||||
compileOptions {
|
||||
coreLibraryDesugaringEnabled true
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
@ -41,22 +51,67 @@ android {
|
||||
main.java.srcDirs += 'src/main/kotlin'
|
||||
}
|
||||
|
||||
buildFeatures {
|
||||
compose true
|
||||
}
|
||||
|
||||
composeOptions {
|
||||
kotlinCompilerExtensionVersion "$composeVersion" // Correlates with org.jetbrains.kotlin.android plugin in settings.gradle
|
||||
}
|
||||
|
||||
defaultConfig {
|
||||
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
|
||||
applicationId "oss.krtirtho.spotube"
|
||||
minSdkVersion flutter.minSdkVersion
|
||||
targetSdkVersion flutter.targetSdkVersion
|
||||
minSdkVersion 24
|
||||
targetSdkVersion 35
|
||||
versionCode flutterVersionCode.toInteger()
|
||||
versionName flutterVersionName
|
||||
multiDexEnabled true
|
||||
}
|
||||
|
||||
signingConfigs {
|
||||
release {
|
||||
keyAlias keystoreProperties['keyAlias']
|
||||
keyPassword keystoreProperties['keyPassword']
|
||||
storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null
|
||||
storePassword keystoreProperties['storePassword']
|
||||
}
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
// TODO: Add your own signing config for the release build.
|
||||
// Signing with the debug keys for now, so `flutter run --release` works.
|
||||
signingConfig signingConfigs.debug
|
||||
signingConfig signingConfigs.release
|
||||
}
|
||||
debug {
|
||||
signingConfig signingConfigs.release
|
||||
}
|
||||
}
|
||||
|
||||
flavorDimensions "default"
|
||||
|
||||
productFlavors {
|
||||
nightly {
|
||||
dimension "default"
|
||||
resValue "string", "app_name_en", "Spotube Nightly"
|
||||
applicationIdSuffix ".nightly"
|
||||
versionNameSuffix "-nightly"
|
||||
signingConfig signingConfigs.release
|
||||
}
|
||||
dev {
|
||||
dimension "default"
|
||||
resValue "string", "app_name_en", "Spotube Dev"
|
||||
applicationIdSuffix ".dev"
|
||||
versionNameSuffix "-dev"
|
||||
signingConfig signingConfigs.release
|
||||
}
|
||||
stable {
|
||||
dimension "default"
|
||||
resValue "string", "app_name_en", "Spotube"
|
||||
signingConfig signingConfigs.release
|
||||
}
|
||||
}
|
||||
|
||||
packagingOptions {
|
||||
resources.excludes += "DebugProbesKt.bin"
|
||||
}
|
||||
}
|
||||
|
||||
@ -64,7 +119,21 @@ flutter {
|
||||
source '../..'
|
||||
}
|
||||
|
||||
def glanceVersion = "1.1.1"
|
||||
dependencies {
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||
implementation 'com.android.support:multidex:1.0.3'
|
||||
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.1.4'
|
||||
|
||||
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.5.1'
|
||||
// other deps so just ignore
|
||||
implementation 'com.android.support:multidex:2.0.1'
|
||||
|
||||
implementation "androidx.glance:glance-appwidget:$glanceVersion"
|
||||
implementation "androidx.glance:glance-appwidget-preview:$glanceVersion"
|
||||
implementation "androidx.glance:glance-preview:$glanceVersion"
|
||||
implementation "androidx.glance:glance-material3:$glanceVersion"
|
||||
implementation "androidx.glance:glance-material:$glanceVersion"
|
||||
implementation "androidx.work:work-runtime-ktx:2.8.1"
|
||||
|
||||
implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.7.3"
|
||||
implementation 'com.google.code.gson:gson:2.11.0'
|
||||
}
|
59
android/app/proguard-rules.pro
vendored
Normal file
@ -0,0 +1,59 @@
|
||||
#Flutter Wrapper
|
||||
# -keep class io.flutter.app.** { *; }
|
||||
-keep class io.flutter.plugin.** { *; }
|
||||
-keep class io.flutter.util.** { *; }
|
||||
-keep class io.flutter.view.** { *; }
|
||||
# -keep class io.flutter.** { *; }
|
||||
-keep class io.flutter.plugins.** { *; }
|
||||
-keep class de.prosiebensat1digital.** { *; }
|
||||
|
||||
-keep class androidx.lifecycle.DefaultLifecycleObserver
|
||||
|
||||
-keepnames class kotlinx.serialization.** { *; }
|
||||
-keepnames class oss.krtirtho.spotube.glance.models.** { *; }
|
||||
-keep @kotlinx.serialization.Serializable class *
|
||||
-keepclassmembers class ** {
|
||||
@kotlinx.serialization.* <fields>;
|
||||
}
|
||||
|
||||
## We don't need beans
|
||||
-dontwarn java.beans.BeanDescriptor
|
||||
-dontwarn java.beans.BeanInfo
|
||||
-dontwarn java.beans.IntrospectionException
|
||||
-dontwarn java.beans.Introspector
|
||||
-dontwarn java.beans.PropertyDescriptor
|
||||
|
||||
## Rules for NewPipeExtractor
|
||||
-keep class org.schabi.newpipe.extractor.timeago.patterns.** { *; }
|
||||
-keep class org.mozilla.javascript.** { *; }
|
||||
-keep class org.mozilla.classfile.ClassFileWriter
|
||||
-dontwarn org.mozilla.javascript.tools.**
|
||||
|
||||
-dontwarn javax.script.AbstractScriptEngine
|
||||
-dontwarn javax.script.Bindings
|
||||
-dontwarn javax.script.Compilable
|
||||
-dontwarn javax.script.CompiledScript
|
||||
-dontwarn javax.script.Invocable
|
||||
-dontwarn javax.script.ScriptContext
|
||||
-dontwarn javax.script.ScriptEngine
|
||||
-dontwarn javax.script.ScriptEngineFactory
|
||||
-dontwarn javax.script.ScriptException
|
||||
-dontwarn javax.script.SimpleBindings
|
||||
-dontwarn jdk.dynalink.CallSiteDescriptor
|
||||
-dontwarn jdk.dynalink.DynamicLinker
|
||||
-dontwarn jdk.dynalink.DynamicLinkerFactory
|
||||
-dontwarn jdk.dynalink.NamedOperation
|
||||
-dontwarn jdk.dynalink.Namespace
|
||||
-dontwarn jdk.dynalink.NamespaceOperation
|
||||
-dontwarn jdk.dynalink.Operation
|
||||
-dontwarn jdk.dynalink.RelinkableCallSite
|
||||
-dontwarn jdk.dynalink.StandardNamespace
|
||||
-dontwarn jdk.dynalink.StandardOperation
|
||||
-dontwarn jdk.dynalink.linker.GuardedInvocation
|
||||
-dontwarn jdk.dynalink.linker.GuardingDynamicLinker
|
||||
-dontwarn jdk.dynalink.linker.LinkRequest
|
||||
-dontwarn jdk.dynalink.linker.LinkerServices
|
||||
-dontwarn jdk.dynalink.linker.TypeBasedGuardingDynamicLinker
|
||||
-dontwarn jdk.dynalink.linker.support.CompositeTypeBasedGuardingDynamicLinker
|
||||
-dontwarn jdk.dynalink.linker.support.Guards
|
||||
-dontwarn jdk.dynalink.support.ChainedCallSite
|
@ -1,7 +1,19 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="oss.krtirtho.spotube">
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<!-- Flutter needs it to communicate with the running application
|
||||
to allow setting breakpoints, to provide hot reload, etc.
|
||||
-->
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<application
|
||||
android:name="${applicationName}"
|
||||
android:allowBackup="false"
|
||||
android:fullBackupContent="false"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name_en"
|
||||
android:requestLegacyExternalStorage="true"
|
||||
android:usesCleartextTraffic="true">
|
||||
<!-- Disable Impeller -->
|
||||
<meta-data
|
||||
android:name="io.flutter.embedding.android.EnableImpeller"
|
||||
android:value="false" />
|
||||
</application>
|
||||
</manifest>
|
@ -1,10 +1,12 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="oss.krtirtho.spotube">
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
|
||||
|
||||
<queries>
|
||||
<!-- If your app opens https URLs -->
|
||||
@ -14,34 +16,120 @@
|
||||
</intent>
|
||||
</queries>
|
||||
|
||||
<application android:label="Spotube" android:name="${applicationName}" android:icon="@mipmap/ic_launcher" android:usesCleartextTraffic="true" android:requestLegacyExternalStorage="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
|
||||
<application
|
||||
android:name="${applicationName}"
|
||||
android:allowBackup="false"
|
||||
android:fullBackupContent="false"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name_en"
|
||||
android:requestLegacyExternalStorage="true"
|
||||
android:usesCleartextTraffic="true">
|
||||
<!-- Enable Impeller -->
|
||||
<!-- <meta-data
|
||||
android:name="io.flutter.embedding.android.EnableImpeller"
|
||||
android:value="false" /> -->
|
||||
|
||||
<activity
|
||||
android:name="com.ryanheise.audioservice.AudioServiceActivity"
|
||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
|
||||
android:exported="true"
|
||||
android:hardwareAccelerated="true"
|
||||
android:launchMode="singleInstance"
|
||||
android:theme="@style/LaunchTheme"
|
||||
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
|
||||
to determine the Window background behind the Flutter UI. -->
|
||||
<meta-data android:name="io.flutter.embedding.android.NormalTheme" android:resource="@style/NormalTheme" />
|
||||
to determine the Window background behind the Flutter UI.
|
||||
-->
|
||||
<meta-data
|
||||
android:name="io.flutter.embedding.android.NormalTheme"
|
||||
android:resource="@style/NormalTheme" />
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
</intent-filter>
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.SEND" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<data android:mimeType="text/*" />
|
||||
</intent-filter>
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
<data android:scheme="spotube" />
|
||||
</intent-filter>
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="es.antonborri.home_widget.action.LAUNCH" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<service android:name="com.ryanheise.audioservice.AudioService" android:exported="false">
|
||||
<!-- AudioService Config -->
|
||||
<service
|
||||
android:name="com.ryanheise.audioservice.AudioService"
|
||||
android:exported="true"
|
||||
android:foregroundServiceType="mediaPlayback">
|
||||
<intent-filter>
|
||||
<action android:name="android.media.browse.MediaBrowserService" />
|
||||
</intent-filter>
|
||||
</service>
|
||||
|
||||
<receiver android:name="com.ryanheise.audioservice.MediaButtonReceiver" android:exported="false">
|
||||
<receiver
|
||||
android:name="com.ryanheise.audioservice.MediaButtonReceiver"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MEDIA_BUTTON" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
<!-- =================== -->
|
||||
|
||||
<meta-data
|
||||
android:name="com.google.android.gms.car.application"
|
||||
android:resource="@xml/automotive_app_desc" />
|
||||
|
||||
<!-- Home Widget config -->
|
||||
<receiver
|
||||
android:name=".glance.HomePlayerWidgetReceiver"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
|
||||
</intent-filter>
|
||||
<meta-data
|
||||
android:name="android.appwidget.provider"
|
||||
android:resource="@xml/home_player_widget_config" />
|
||||
</receiver>
|
||||
|
||||
<receiver
|
||||
android:name="es.antonborri.home_widget.HomeWidgetBackgroundReceiver"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="es.antonborri.home_widget.action.BACKGROUND" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<service
|
||||
android:name="es.antonborri.home_widget.HomeWidgetBackgroundService"
|
||||
android:exported="true"
|
||||
android:permission="android.permission.BIND_JOB_SERVICE" />
|
||||
<!-- =================== -->
|
||||
|
||||
<!-- 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" />
|
||||
<meta-data
|
||||
android:name="flutterEmbedding"
|
||||
android:value="2" />
|
||||
</application>
|
||||
</manifest>
|
@ -1,16 +1,21 @@
|
||||
// Generated file.
|
||||
//
|
||||
// If you wish to remove Flutter's multidex support, delete this entire file.
|
||||
//
|
||||
// Modifications to this file should be done in a copy under a different name
|
||||
// as this file may be regenerated.
|
||||
|
||||
package io.flutter.app;
|
||||
|
||||
import android.app.Application;
|
||||
import android.content.Context;
|
||||
import androidx.annotation.CallSuper;
|
||||
import androidx.multidex.MultiDex;
|
||||
|
||||
/**
|
||||
* Extension of {@link io.flutter.app.FlutterApplication}, adding multidex support.
|
||||
* Extension of {@link android.app.Application}, adding multidex support.
|
||||
*/
|
||||
public class FlutterMultiDexApplication extends FlutterApplication {
|
||||
public class FlutterMultiDexApplication extends Application {
|
||||
@Override
|
||||
@CallSuper
|
||||
protected void attachBaseContext(Context base) {
|
||||
|
@ -0,0 +1,207 @@
|
||||
package oss.krtirtho.spotube.glance
|
||||
|
||||
import HomeWidgetGlanceState
|
||||
import HomeWidgetGlanceStateDefinition
|
||||
import android.R
|
||||
import android.content.Context
|
||||
import android.graphics.drawable.Icon
|
||||
import android.net.Uri
|
||||
import android.util.Log
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.unit.DpSize
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.glance.GlanceId
|
||||
import androidx.glance.GlanceModifier
|
||||
import androidx.glance.GlanceTheme
|
||||
import androidx.glance.Image
|
||||
import androidx.glance.ImageProvider
|
||||
import androidx.glance.LocalSize
|
||||
import androidx.glance.action.ActionParameters
|
||||
import androidx.glance.action.actionParametersOf
|
||||
import androidx.glance.action.clickable
|
||||
import androidx.glance.background
|
||||
import androidx.glance.appwidget.GlanceAppWidget
|
||||
import androidx.glance.appwidget.SizeMode
|
||||
import androidx.glance.appwidget.action.ActionCallback
|
||||
import androidx.glance.appwidget.action.actionRunCallback
|
||||
import androidx.glance.appwidget.background
|
||||
import androidx.glance.appwidget.components.CircleIconButton
|
||||
import androidx.glance.appwidget.components.Scaffold
|
||||
import androidx.glance.appwidget.cornerRadius
|
||||
import androidx.glance.appwidget.provideContent
|
||||
import androidx.glance.background
|
||||
import androidx.glance.currentState
|
||||
import androidx.glance.layout.Alignment
|
||||
import androidx.glance.layout.Box
|
||||
import androidx.glance.layout.Column
|
||||
import androidx.glance.layout.ContentScale
|
||||
import androidx.glance.layout.Row
|
||||
import androidx.glance.layout.Spacer
|
||||
import androidx.glance.layout.fillMaxSize
|
||||
import androidx.glance.layout.fillMaxWidth
|
||||
import androidx.glance.layout.padding
|
||||
import androidx.glance.layout.size
|
||||
import androidx.glance.preview.ExperimentalGlancePreviewApi
|
||||
import androidx.glance.preview.Preview
|
||||
import androidx.glance.state.GlanceStateDefinition
|
||||
import com.google.gson.Gson
|
||||
import es.antonborri.home_widget.HomeWidgetBackgroundIntent
|
||||
import es.antonborri.home_widget.actionStartActivity
|
||||
import oss.krtirtho.spotube.MainActivity
|
||||
import oss.krtirtho.spotube.glance.models.Track
|
||||
import oss.krtirtho.spotube.glance.widgets.FlutterAssetImageProvider
|
||||
import oss.krtirtho.spotube.glance.widgets.TrackDetailsView
|
||||
import oss.krtirtho.spotube.glance.widgets.TrackProgress
|
||||
|
||||
val gson = Gson()
|
||||
val serverAddressKey = ActionParameters.Key<String>("serverAddress")
|
||||
|
||||
class Breakpoints {
|
||||
companion object {
|
||||
val SMALL_SQUARE = DpSize(100.dp, 100.dp)
|
||||
val HORIZONTAL_RECTANGLE = DpSize(250.dp, 100.dp)
|
||||
val BIG_SQUARE = DpSize(250.dp, 250.dp)
|
||||
}
|
||||
}
|
||||
|
||||
class HomePlayerWidget : GlanceAppWidget() {
|
||||
|
||||
override val sizeMode = SizeMode.Responsive(
|
||||
setOf(
|
||||
Breakpoints.SMALL_SQUARE,
|
||||
Breakpoints.HORIZONTAL_RECTANGLE,
|
||||
Breakpoints.BIG_SQUARE
|
||||
)
|
||||
)
|
||||
|
||||
override val stateDefinition: GlanceStateDefinition<*>?
|
||||
get() = HomeWidgetGlanceStateDefinition()
|
||||
|
||||
override suspend fun provideGlance(context: Context, id: GlanceId) {
|
||||
provideContent {
|
||||
GlanceContent(context, currentState())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@OptIn(ExperimentalGlancePreviewApi::class)
|
||||
@Preview(widthDp = 100, heightDp = 100)
|
||||
@Composable
|
||||
private fun GlanceContent(context: Context, currentState: HomeWidgetGlanceState) {
|
||||
val prefs = currentState.preferences
|
||||
val size = LocalSize.current
|
||||
|
||||
val activeTrackStr = prefs.getString("activeTrack", null)
|
||||
|
||||
val isPlaying = prefs.getBoolean("isPlaying", false)
|
||||
val playbackServerAddress = prefs.getString("playbackServerAddress", null) ?: ""
|
||||
|
||||
var activeTrack: Track? = null
|
||||
if (activeTrackStr != null) {
|
||||
activeTrack = gson.fromJson(activeTrackStr, Track::class.java)
|
||||
}
|
||||
|
||||
|
||||
val playIcon = Icon.createWithResource(context, R.drawable.ic_media_play);
|
||||
val pauseIcon = Icon.createWithResource(context, R.drawable.ic_media_pause);
|
||||
val previousIcon = Icon.createWithResource(context, R.drawable.ic_media_previous);
|
||||
val nextIcon = Icon.createWithResource(context, R.drawable.ic_media_next);
|
||||
|
||||
GlanceTheme {
|
||||
Box(
|
||||
modifier = GlanceModifier
|
||||
.fillMaxSize()
|
||||
.cornerRadius(8.dp)
|
||||
.background(
|
||||
color = GlanceTheme.colors.surface.getColor(context)
|
||||
)
|
||||
.clickable {
|
||||
actionStartActivity<MainActivity>(context)
|
||||
}
|
||||
,
|
||||
) {
|
||||
Box(
|
||||
modifier = GlanceModifier
|
||||
.background(
|
||||
color =
|
||||
GlanceTheme.colors.surface.getColor(context)
|
||||
.copy(alpha = 0.5f),
|
||||
)
|
||||
.fillMaxSize(),
|
||||
) {}
|
||||
Column(
|
||||
modifier = GlanceModifier.padding(top = 10.dp, start = 10.dp, end = 10.dp)
|
||||
) {
|
||||
Row(verticalAlignment = Alignment.Vertical.CenterVertically) {
|
||||
TrackDetailsView(activeTrack)
|
||||
}
|
||||
Spacer(modifier = GlanceModifier.size(6.dp))
|
||||
if (size != Breakpoints.SMALL_SQUARE) {
|
||||
TrackProgress(prefs)
|
||||
}
|
||||
Spacer(modifier = GlanceModifier.size(6.dp))
|
||||
Row(
|
||||
modifier = GlanceModifier.fillMaxWidth(),
|
||||
horizontalAlignment = Alignment.Horizontal.CenterHorizontally
|
||||
) {
|
||||
CircleIconButton(
|
||||
imageProvider = ImageProvider(previousIcon),
|
||||
contentDescription = "Previous",
|
||||
onClick = actionRunCallback<PreviousAction>(
|
||||
parameters = actionParametersOf(serverAddressKey to playbackServerAddress)
|
||||
)
|
||||
)
|
||||
Spacer(modifier = GlanceModifier.size(6.dp))
|
||||
CircleIconButton(
|
||||
imageProvider =
|
||||
if (isPlaying) ImageProvider(pauseIcon)
|
||||
else ImageProvider(playIcon),
|
||||
contentDescription = "Play/Pause",
|
||||
onClick = actionRunCallback<PlayPauseAction>(
|
||||
parameters = actionParametersOf(serverAddressKey to playbackServerAddress)
|
||||
)
|
||||
)
|
||||
Spacer(modifier = GlanceModifier.size(6.dp))
|
||||
CircleIconButton(
|
||||
imageProvider = ImageProvider(nextIcon),
|
||||
contentDescription = "Previous",
|
||||
onClick = actionRunCallback<NextAction>(
|
||||
parameters = actionParametersOf(
|
||||
serverAddressKey to playbackServerAddress
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class PlayPauseAction : InteractiveAction("toggle-playback")
|
||||
class NextAction : InteractiveAction("next")
|
||||
class PreviousAction : InteractiveAction("previous")
|
||||
|
||||
|
||||
abstract class InteractiveAction(val command: String) : ActionCallback {
|
||||
override suspend fun onAction(
|
||||
context: Context,
|
||||
glanceId: GlanceId,
|
||||
parameters: ActionParameters
|
||||
) {
|
||||
val serverAddress = parameters[serverAddressKey] ?: ""
|
||||
|
||||
Log.d("HomePlayerWidget", "Sending command $command to $serverAddress")
|
||||
|
||||
if (serverAddress == null || serverAddress.isEmpty()) {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
val backgroundIntent = HomeWidgetBackgroundIntent.getBroadcast(
|
||||
context,
|
||||
Uri.parse("spotube://playback/$command?serverAddress=$serverAddress")
|
||||
)
|
||||
backgroundIntent.send()
|
||||
}
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
package oss.krtirtho.spotube.glance
|
||||
|
||||
import HomeWidgetGlanceWidgetReceiver
|
||||
|
||||
class HomePlayerWidgetReceiver : HomeWidgetGlanceWidgetReceiver<HomePlayerWidget>() {
|
||||
override val glanceAppWidget = HomePlayerWidget()
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
package oss.krtirtho.spotube.glance.models
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class AlbumSimple(
|
||||
@SerializedName("album_type")
|
||||
val albumType: AlbumType?,
|
||||
|
||||
@SerializedName("available_markets")
|
||||
val availableMarkets: List<Market>?,
|
||||
|
||||
val href: String?,
|
||||
val id: String?,
|
||||
val images: List<Image>?,
|
||||
val name: String?,
|
||||
|
||||
@SerializedName("release_date")
|
||||
val releaseDate: String?,
|
||||
|
||||
@SerializedName("release_date_precision")
|
||||
val releaseDatePrecision: DatePrecision?,
|
||||
|
||||
val type: String?,
|
||||
val uri: String?,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
enum class AlbumType {
|
||||
album,
|
||||
single,
|
||||
compilation
|
||||
}
|
||||
|
||||
enum class DatePrecision {
|
||||
year,
|
||||
month,
|
||||
day
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
package oss.krtirtho.spotube.glance.models
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class Artist(
|
||||
val href: String?,
|
||||
val id: String?,
|
||||
val name: String?,
|
||||
val type: String?,
|
||||
val uri: String?,
|
||||
|
||||
val followers: Followers?,
|
||||
val genres: List<String>?,
|
||||
val images: List<Image>?,
|
||||
|
||||
@SerializedName("popularity")
|
||||
val popularity: Int?
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class Followers(
|
||||
val total: Int?
|
||||
)
|
@ -0,0 +1,10 @@
|
||||
package oss.krtirtho.spotube.glance.models
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class Image(
|
||||
val height: Int?,
|
||||
val width: Int?,
|
||||
val path: String,
|
||||
)
|
@ -0,0 +1,37 @@
|
||||
package oss.krtirtho.spotube.glance.models
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlin.time.Duration.Companion.milliseconds
|
||||
|
||||
@Serializable
|
||||
data class Track(
|
||||
val album: AlbumSimple?, val artists: List<Artist>?,
|
||||
|
||||
@SerializedName("available_markets") val availableMarkets: List<Market>?,
|
||||
|
||||
@SerializedName("disc_number") val discNumber: Int?,
|
||||
|
||||
@SerializedName("duration_ms") val durationMs: Int,
|
||||
|
||||
val explicit: Boolean?, val href: String?, val id: String?,
|
||||
|
||||
@SerializedName("is_playable") val isPlayable: Boolean?,
|
||||
|
||||
val name: String?,
|
||||
|
||||
@SerializedName("popularity") val popularity: Int?,
|
||||
|
||||
@SerializedName("preview_url") val previewUrl: String?,
|
||||
|
||||
@SerializedName("track_number") val trackNumber: Int?,
|
||||
|
||||
val type: String?, val uri: String?
|
||||
) {
|
||||
val duration: kotlin.time.Duration
|
||||
get() = durationMs.toLong().milliseconds
|
||||
}
|
||||
|
||||
enum class Market {
|
||||
AD, AE, AF, AG, AI, AL, AM, AO, AQ, AR, AS, AT, AU, AW, AX, AZ, BA, BB, BD, BE, BF, BG, BH, BI, BJ, BL, BM, BN, BO, BQ, BR, BS, BT, BV, BW, BY, BZ, CA, CC, CD, CF, CG, CH, CI, CK, CL, CM, CN, CO, CR, CU, CV, CW, CX, CY, CZ, DE, DJ, DK, DM, DO, DZ, EC, EE, EG, EH, ER, ES, ET, FI, FJ, FK, FM, FO, FR, GA, GB, GD, GE, GF, GG, GH, GI, GL, GM, GN, GP, GQ, GR, GS, GT, GU, GW, GY, HK, HM, HN, HR, HT, HU, ID, IE, IL, IM, IN, IO, IQ, IR, IS, IT, JE, JM, JO, JP, KE, KG, KH, KI, KM, KN, KP, KR, KW, KY, KZ, LA, LB, LC, LI, LK, LR, LS, LT, LU, LV, LY, MA, MC, MD, ME, MF, MG, MH, MK, ML, MM, MN, MO, MP, MQ, MR, MS, MT, MU, MV, MW, MX, MY, MZ, NA, NC, NE, NF, NG, NI, NL, NO, NP, NR, NU, NZ, OM, PA, PE, PF, PG, PH, PK, PL, PM, PN, PR, PS, PT, PW, PY, QA, RE, RO, RS, RU, RW, SA, SB, SC, SD, SE, SG, SH, SI, SJ, SK, SL, SM, SN, SO, SR, SS, ST, SV, SX, SY, SZ, TC, TD, TF, TG, TH, TJ, TK, TL, TM, TN, TO, TR, TT, TV, TW, TZ, UA, UG, UM, US, UY, UZ, VA, VC, VE, VG, VI, VN, VU, WF, WS, XK, YE, YT, ZA, ZM, ZW,
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
package oss.krtirtho.spotube.glance.widgets
|
||||
|
||||
import android.graphics.BitmapFactory
|
||||
import android.util.Base64
|
||||
import androidx.glance.ImageProvider
|
||||
|
||||
@Suppress("FunctionName")
|
||||
fun Base64ImageProvider(base64: String): ImageProvider {
|
||||
var bytes = Base64.decode(base64, Base64.DEFAULT);
|
||||
|
||||
var bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.size);
|
||||
|
||||
return ImageProvider(bitmap)
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
package oss.krtirtho.spotube.glance.widgets
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.BitmapFactory
|
||||
import androidx.glance.ImageProvider
|
||||
|
||||
@Suppress("FunctionName")
|
||||
fun FlutterAssetImageProvider(context: Context, path: String): ImageProvider {
|
||||
var inputStream = context.assets.open("flutter_assets/$path")
|
||||
|
||||
return ImageProvider(
|
||||
BitmapFactory.decodeStream(inputStream)
|
||||
)
|
||||
}
|
@ -0,0 +1,78 @@
|
||||
package oss.krtirtho.spotube.glance.widgets
|
||||
|
||||
import android.graphics.BitmapFactory
|
||||
import android.net.Uri
|
||||
import android.util.Log
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.glance.GlanceModifier
|
||||
import androidx.glance.GlanceTheme
|
||||
import androidx.glance.Image
|
||||
import androidx.glance.ImageProvider
|
||||
import androidx.glance.LocalContext
|
||||
import androidx.glance.LocalSize
|
||||
import androidx.glance.appwidget.cornerRadius
|
||||
import androidx.glance.layout.Alignment
|
||||
import androidx.glance.layout.Row
|
||||
import androidx.glance.layout.Column
|
||||
import androidx.glance.layout.ContentScale
|
||||
import androidx.glance.layout.Spacer
|
||||
import androidx.glance.layout.size
|
||||
import androidx.glance.text.FontWeight
|
||||
import androidx.glance.text.Text
|
||||
import androidx.glance.text.TextStyle
|
||||
import oss.krtirtho.spotube.glance.Breakpoints
|
||||
import oss.krtirtho.spotube.glance.models.Track
|
||||
|
||||
@Composable
|
||||
fun TrackDetailsView(activeTrack: Track?) {
|
||||
val context = LocalContext.current
|
||||
|
||||
val size = LocalSize.current
|
||||
|
||||
val artistStr = activeTrack?.artists?.map { it.name }?.joinToString(", ") ?: "<No Artist>"
|
||||
val imgLocalPath = activeTrack?.album?.images?.get(0)?.path;
|
||||
val title = activeTrack?.name ?: "<No Track>"
|
||||
|
||||
|
||||
Image(
|
||||
provider =
|
||||
if (imgLocalPath == null)
|
||||
ImageProvider(
|
||||
BitmapFactory.decodeResource(
|
||||
context.resources,
|
||||
android.R.drawable.ic_delete
|
||||
)
|
||||
)
|
||||
else ImageProvider(BitmapFactory.decodeFile(imgLocalPath)),
|
||||
contentDescription = "Album Art",
|
||||
modifier = GlanceModifier.cornerRadius(8.dp)
|
||||
.size(
|
||||
if (size.height < 200.dp) 50.dp
|
||||
else 100.dp
|
||||
),
|
||||
contentScale = ContentScale.Fit
|
||||
)
|
||||
Spacer(modifier = GlanceModifier.size(6.dp))
|
||||
Column {
|
||||
Text(
|
||||
text = title,
|
||||
style = TextStyle(
|
||||
fontSize = 16.sp,
|
||||
fontWeight = FontWeight.Bold,
|
||||
color = GlanceTheme.colors.onBackground
|
||||
),
|
||||
)
|
||||
if (size != Breakpoints.SMALL_SQUARE) {
|
||||
Spacer(modifier = GlanceModifier.size(6.dp))
|
||||
Text(
|
||||
text = artistStr,
|
||||
style = TextStyle(
|
||||
fontSize = 14.sp,
|
||||
color = GlanceTheme.colors.onBackground
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,77 @@
|
||||
package oss.krtirtho.spotube.glance.widgets
|
||||
|
||||
import android.content.SharedPreferences
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.glance.GlanceModifier
|
||||
import androidx.glance.GlanceTheme
|
||||
import androidx.glance.LocalSize
|
||||
import androidx.glance.appwidget.LinearProgressIndicator
|
||||
import androidx.glance.layout.Column
|
||||
import androidx.glance.layout.Row
|
||||
import androidx.glance.layout.Spacer
|
||||
import androidx.glance.layout.fillMaxWidth
|
||||
import androidx.glance.layout.size
|
||||
import androidx.glance.text.Text
|
||||
import androidx.glance.text.TextStyle
|
||||
import kotlin.math.max
|
||||
import kotlin.time.Duration
|
||||
import kotlin.time.Duration.Companion.seconds
|
||||
import oss.krtirtho.spotube.glance.Breakpoints
|
||||
|
||||
fun Duration.format(): String {
|
||||
return this.toComponents { hour, minutes, seconds, nanoseconds ->
|
||||
var paddedSeconds = seconds.toString().padStart(2, '0')
|
||||
var paddedMinutes = minutes.toString().padStart(2, '0')
|
||||
var paddedHour = hour.toString().padStart(2, '0')
|
||||
if (hour == 0L) {
|
||||
"$paddedMinutes:$paddedSeconds"
|
||||
} else {
|
||||
"$paddedHour:$paddedMinutes:$paddedSeconds"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun TrackProgress(prefs: SharedPreferences) {
|
||||
val size = LocalSize.current
|
||||
val position = prefs.getInt("position", 0).seconds
|
||||
var duration = prefs.getInt("duration", 0).seconds
|
||||
|
||||
var progress = position.inWholeSeconds.toFloat() / max(duration.inWholeSeconds.toFloat(), 1.0f)
|
||||
|
||||
var textStyle =
|
||||
TextStyle(
|
||||
color = GlanceTheme.colors.onBackground,
|
||||
)
|
||||
|
||||
if (size == Breakpoints.HORIZONTAL_RECTANGLE) {
|
||||
Row(modifier = GlanceModifier.fillMaxWidth()) {
|
||||
Text(text = position.format(), style = textStyle)
|
||||
Spacer(modifier = GlanceModifier.size(6.dp))
|
||||
LinearProgressIndicator(
|
||||
progress = progress,
|
||||
modifier = GlanceModifier.defaultWeight(),
|
||||
color = GlanceTheme.colors.primary,
|
||||
backgroundColor = GlanceTheme.colors.primaryContainer,
|
||||
)
|
||||
Spacer(modifier = GlanceModifier.size(6.dp))
|
||||
Text(text = duration.format(), style = textStyle)
|
||||
}
|
||||
} else {
|
||||
Column(modifier = GlanceModifier.fillMaxWidth()) {
|
||||
LinearProgressIndicator(
|
||||
progress = progress,
|
||||
modifier = GlanceModifier.fillMaxWidth(),
|
||||
color = GlanceTheme.colors.primary,
|
||||
backgroundColor = GlanceTheme.colors.primaryContainer,
|
||||
)
|
||||
Spacer(modifier = GlanceModifier.size(6.dp))
|
||||
Row(modifier = GlanceModifier.fillMaxWidth()) {
|
||||
Text(text = position.format(), style = textStyle)
|
||||
Spacer(modifier = GlanceModifier.defaultWeight())
|
||||
Text(text = duration.format(), style = textStyle)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
BIN
android/app/src/main/res/drawable-hdpi-v31/android12branding.png
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
android/app/src/main/res/drawable-hdpi/android12splash.png
Normal file
After Width: | Height: | Size: 52 KiB |
BIN
android/app/src/main/res/drawable-hdpi/branding.png
Normal file
After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 8.3 KiB After Width: | Height: | Size: 11 KiB |
BIN
android/app/src/main/res/drawable-hdpi/splash.png
Normal file
After Width: | Height: | Size: 22 KiB |
BIN
android/app/src/main/res/drawable-mdpi-v31/android12branding.png
Normal file
After Width: | Height: | Size: 7.6 KiB |
BIN
android/app/src/main/res/drawable-mdpi/android12splash.png
Normal file
After Width: | Height: | Size: 27 KiB |
BIN
android/app/src/main/res/drawable-mdpi/branding.png
Normal file
After Width: | Height: | Size: 7.6 KiB |
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 5.7 KiB |
BIN
android/app/src/main/res/drawable-mdpi/splash.png
Normal file
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 12 KiB |
BIN
android/app/src/main/res/drawable-night-hdpi/android12splash.png
Normal file
After Width: | Height: | Size: 52 KiB |
After Width: | Height: | Size: 7.6 KiB |
BIN
android/app/src/main/res/drawable-night-mdpi/android12splash.png
Normal file
After Width: | Height: | Size: 27 KiB |
After Width: | Height: | Size: 13 KiB |
After Width: | Height: | Size: 83 KiB |
After Width: | Height: | Size: 19 KiB |
After Width: | Height: | Size: 162 KiB |
After Width: | Height: | Size: 19 KiB |
After Width: | Height: | Size: 247 KiB |
BIN
android/app/src/main/res/drawable-v21/background.png
Normal file
After Width: | Height: | Size: 3.0 MiB |
@ -1,12 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Modify this file to customize your launch splash screen -->
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:drawable="?android:colorBackground" />
|
||||
|
||||
<!-- You can insert your own image assets here -->
|
||||
<!-- <item>
|
||||
<bitmap
|
||||
android:gravity="center"
|
||||
android:src="@mipmap/launch_image" />
|
||||
</item> -->
|
||||
<item>
|
||||
<bitmap android:gravity="fill" android:src="@drawable/background"/>
|
||||
</item>
|
||||
<item>
|
||||
<bitmap android:gravity="center" android:src="@drawable/splash"/>
|
||||
</item>
|
||||
<item android:bottom="0dp">
|
||||
<bitmap android:gravity="bottom" android:src="@drawable/branding"/>
|
||||
</item>
|
||||
</layer-list>
|
||||
|
After Width: | Height: | Size: 13 KiB |
BIN
android/app/src/main/res/drawable-xhdpi/android12splash.png
Normal file
After Width: | Height: | Size: 83 KiB |
BIN
android/app/src/main/res/drawable-xhdpi/branding.png
Normal file
After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 18 KiB |
BIN
android/app/src/main/res/drawable-xhdpi/splash.png
Normal file
After Width: | Height: | Size: 35 KiB |
After Width: | Height: | Size: 19 KiB |
BIN
android/app/src/main/res/drawable-xxhdpi/android12splash.png
Normal file
After Width: | Height: | Size: 162 KiB |
BIN
android/app/src/main/res/drawable-xxhdpi/branding.png
Normal file
After Width: | Height: | Size: 19 KiB |
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 34 KiB |
BIN
android/app/src/main/res/drawable-xxhdpi/splash.png
Normal file
After Width: | Height: | Size: 70 KiB |
After Width: | Height: | Size: 19 KiB |
BIN
android/app/src/main/res/drawable-xxxhdpi/android12splash.png
Normal file
After Width: | Height: | Size: 247 KiB |
BIN
android/app/src/main/res/drawable-xxxhdpi/branding.png
Normal file
After Width: | Height: | Size: 19 KiB |
Before Width: | Height: | Size: 43 KiB After Width: | Height: | Size: 55 KiB |
BIN
android/app/src/main/res/drawable-xxxhdpi/splash.png
Normal file
After Width: | Height: | Size: 112 KiB |
BIN
android/app/src/main/res/drawable/background.png
Normal file
After Width: | Height: | Size: 3.0 MiB |
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>
|
@ -1,12 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Modify this file to customize your launch splash screen -->
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:drawable="@android:color/white" />
|
||||
|
||||
<!-- You can insert your own image assets here -->
|
||||
<!-- <item>
|
||||
<bitmap
|
||||
android:gravity="center"
|
||||
android:src="@mipmap/launch_image" />
|
||||
</item> -->
|
||||
<item>
|
||||
<bitmap android:gravity="fill" android:src="@drawable/background"/>
|
||||
</item>
|
||||
<item>
|
||||
<bitmap android:gravity="center" android:src="@drawable/splash"/>
|
||||
</item>
|
||||
<item android:bottom="0dp">
|
||||
<bitmap android:gravity="bottom" android:src="@drawable/branding"/>
|
||||
</item>
|
||||
</layer-list>
|
||||
|
@ -1,5 +1,9 @@
|
||||
<?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"/>
|
||||
<foreground>
|
||||
<inset
|
||||
android:drawable="@drawable/ic_launcher_foreground"
|
||||
android:inset="16%" />
|
||||
</foreground>
|
||||
</adaptive-icon>
|
||||
|
Before Width: | Height: | Size: 6.9 KiB After Width: | Height: | Size: 5.0 KiB |
Before Width: | Height: | Size: 4.0 KiB After Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 7.8 KiB |
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 23 KiB |
23
android/app/src/main/res/values-night-v31/styles.xml
Normal file
@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off -->
|
||||
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
|
||||
<item name="android:forceDarkAllowed">false</item>
|
||||
<item name="android:windowFullscreen">false</item>
|
||||
<item name="android:windowDrawsSystemBarBackgrounds">false</item>
|
||||
<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
|
||||
<item name="android:windowSplashScreenBackground">#000000</item>
|
||||
<item name="android:windowSplashScreenBrandingImage">@drawable/android12branding</item>
|
||||
<item name="android:windowSplashScreenAnimatedIcon">@drawable/android12splash</item>
|
||||
<item name="android:windowSplashScreenIconBackgroundColor">#000000</item>
|
||||
</style>
|
||||
<!-- Theme applied to the Android Window as soon as the process has started.
|
||||
This theme determines the color of the Android Window while your
|
||||
Flutter UI initializes, as well as behind your Flutter UI while its
|
||||
running.
|
||||
|
||||
This Theme is only used starting with V2 of Flutter's Android embedding. -->
|
||||
<style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
|
||||
<item name="android:windowBackground">?android:colorBackground</item>
|
||||
</style>
|
||||
</resources>
|
@ -5,6 +5,10 @@
|
||||
<!-- Show a splash screen on the activity. Automatically removed when
|
||||
Flutter draws its first frame -->
|
||||
<item name="android:windowBackground">@drawable/launch_background</item>
|
||||
<item name="android:forceDarkAllowed">false</item>
|
||||
<item name="android:windowFullscreen">false</item>
|
||||
<item name="android:windowDrawsSystemBarBackgrounds">false</item>
|
||||
<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
|
||||
</style>
|
||||
<!-- Theme applied to the Android Window as soon as the process has started.
|
||||
This theme determines the color of the Android Window while your
|
||||
|
23
android/app/src/main/res/values-v31/styles.xml
Normal file
@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off -->
|
||||
<style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
|
||||
<item name="android:forceDarkAllowed">false</item>
|
||||
<item name="android:windowFullscreen">false</item>
|
||||
<item name="android:windowDrawsSystemBarBackgrounds">false</item>
|
||||
<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
|
||||
<item name="android:windowSplashScreenBackground">#000000</item>
|
||||
<item name="android:windowSplashScreenBrandingImage">@drawable/android12branding</item>
|
||||
<item name="android:windowSplashScreenAnimatedIcon">@drawable/android12splash</item>
|
||||
<item name="android:windowSplashScreenIconBackgroundColor">#000000</item>
|
||||
</style>
|
||||
<!-- Theme applied to the Android Window as soon as the process has started.
|
||||
This theme determines the color of the Android Window while your
|
||||
Flutter UI initializes, as well as behind your Flutter UI while its
|
||||
running.
|
||||
|
||||
This Theme is only used starting with V2 of Flutter's Android embedding. -->
|
||||
<style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
|
||||
<item name="android:windowBackground">?android:colorBackground</item>
|
||||
</style>
|
||||
</resources>
|
@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="ic_launcher_background">#ffffff</color>
|
||||
<color name="ic_launcher_background">#242832</color>
|
||||
</resources>
|
@ -5,6 +5,10 @@
|
||||
<!-- Show a splash screen on the activity. Automatically removed when
|
||||
Flutter draws its first frame -->
|
||||
<item name="android:windowBackground">@drawable/launch_background</item>
|
||||
<item name="android:forceDarkAllowed">false</item>
|
||||
<item name="android:windowFullscreen">false</item>
|
||||
<item name="android:windowDrawsSystemBarBackgrounds">false</item>
|
||||
<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
|
||||
</style>
|
||||
<!-- Theme applied to the Android Window as soon as the process has started.
|
||||
This theme determines the color of the Android Window while your
|
||||
|
3
android/app/src/main/res/xml/automotive_app_desc.xml
Normal file
@ -0,0 +1,3 @@
|
||||
<automotiveApp>
|
||||
<uses name="media" />
|
||||
</automotiveApp>
|
@ -0,0 +1,7 @@
|
||||
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:initialLayout="@layout/glance_default_loading_layout"
|
||||
android:minWidth="100dp"
|
||||
android:minHeight="100dp"
|
||||
android:resizeMode="horizontal|vertical"
|
||||
android:updatePeriodMillis="10000">
|
||||
</appwidget-provider>
|