Compare commits
37 Commits
develop
...
continuous
| Author | SHA1 | Date | |
|---|---|---|---|
| 1b682addf2 | |||
| c9c4423fc4 | |||
| e3d5d30cb8 | |||
| a60ecc941d | |||
| e270675a30 | |||
| aca309e39d | |||
| 57df86bc6a | |||
| ea54f06960 | |||
| 1aa88b43b0 | |||
| 64dd6babab | |||
| 29adecba56 | |||
| ae7c8c9d7c | |||
| becaa8b511 | |||
| 9e3a53aa93 | |||
| a74531cea7 | |||
| 3a7202521c | |||
| 014f3c0082 | |||
| ca75a8842d | |||
| b91239002d | |||
| 43bd93aa82 | |||
| ef254ab421 | |||
| 1872aa2e12 | |||
| 07bedb3c47 | |||
| 6289f17c78 | |||
| 199c9eb5cc | |||
| af12903917 | |||
| 46c0e87187 | |||
| 5f0fbe1c3d | |||
| b5ed80c9d9 | |||
| acb260ee5e | |||
| 9c6ef68934 | |||
| d9bf42120c | |||
| c84a66142a | |||
| 8cd5ceb8b2 | |||
| b790859272 | |||
| 83ade4d4db | |||
| 1ceb377434 |
@ -1,7 +1,15 @@
|
||||
{
|
||||
"parser": "babel-eslint",
|
||||
"parser": "@babel/eslint-parser",
|
||||
"extends": [
|
||||
"airbnb"
|
||||
"eslint:recommended",
|
||||
"plugin:react/recommended",
|
||||
"plugin:react-hooks/recommended",
|
||||
"plugin:import/recommended"
|
||||
],
|
||||
"plugins": [
|
||||
"react",
|
||||
"react-hooks",
|
||||
"import"
|
||||
],
|
||||
"rules": {
|
||||
"react/jsx-filename-extension": 0,
|
||||
@ -11,14 +19,42 @@
|
||||
"react/prop-types": 0,
|
||||
"linebreak-style": 0,
|
||||
"no-case-declarations": 0,
|
||||
"camelcase": 0
|
||||
"camelcase": 0,
|
||||
"import/no-unresolved": 0,
|
||||
"import/named": 0,
|
||||
"import/namespace": 0,
|
||||
"import/default": 0,
|
||||
"import/export": 0,
|
||||
"no-unused-vars": ["warn", { "args": "none", "varsIgnorePattern": "^_" }],
|
||||
"react/display-name": 0,
|
||||
"no-prototype-builtins": 0,
|
||||
"no-mixed-spaces-and-tabs": 0,
|
||||
"no-redeclare": 0,
|
||||
"no-undef": 0,
|
||||
"react/jsx-no-target-blank": 0,
|
||||
"react-hooks/exhaustive-deps": 0,
|
||||
"no-empty": 0,
|
||||
"no-extra-boolean-cast": 0,
|
||||
"no-useless-escape": 0,
|
||||
"no-inner-declarations": 0,
|
||||
"no-unreachable": 0,
|
||||
"react-hooks/rules-of-hooks": 0,
|
||||
"no-constant-condition": 0,
|
||||
"no-empty-pattern": 0
|
||||
},
|
||||
"globals": {
|
||||
"fetch": true
|
||||
"fetch": true,
|
||||
"$": true
|
||||
},
|
||||
"env": {
|
||||
"jest": true,
|
||||
"browser": true,
|
||||
"es6": true
|
||||
"es6": true,
|
||||
"node": true
|
||||
},
|
||||
"settings": {
|
||||
"react": {
|
||||
"version": "detect"
|
||||
}
|
||||
}
|
||||
}
|
||||
184
.gitea/workflows/ci.yml
Normal file
@ -0,0 +1,184 @@
|
||||
name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- '**'
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: false
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Lint
|
||||
run: npm run lint
|
||||
|
||||
- name: Test
|
||||
run: npm test
|
||||
|
||||
- name: Notify success (ntfy)
|
||||
if: success()
|
||||
run: |
|
||||
curl -fsS \
|
||||
-H "Title: Iris CI success" \
|
||||
-H "Priority: low" \
|
||||
-H "Tags: success,iris" \
|
||||
-H "Actions: view, Changes, ${{ gitea.server_url }}/${{ gitea.repository }}/commit/${{ gitea.sha }}; view, Build, ${{ gitea.server_url }}/${{ gitea.repository }}/actions/runs/${{ gitea.run_id }}" \
|
||||
-d "✅ Build succeeded: ${{ gitea.repository }} @ ${{ gitea.sha }}" \
|
||||
https://ntfy.unbl.ink/drone
|
||||
|
||||
- name: Notify failure (ntfy)
|
||||
if: failure()
|
||||
run: |
|
||||
curl -fsS \
|
||||
-H "Title: Iris CI failure" \
|
||||
-H "Priority: high" \
|
||||
-H "Tags: failure,iris" \
|
||||
-H "Actions: view, Changes, ${{ gitea.server_url }}/${{ gitea.repository }}/commit/${{ gitea.sha }}; view, Build, ${{ gitea.server_url }}/${{ gitea.repository }}/actions/runs/${{ gitea.run_id }}" \
|
||||
-d "❌ Build failed: ${{ gitea.repository }} @ ${{ gitea.sha }}" \
|
||||
https://ntfy.unbl.ink/drone
|
||||
|
||||
deploy:
|
||||
if: github.ref == 'refs/heads/main' && needs.test.result == 'success'
|
||||
runs-on: ubuntu-latest
|
||||
needs: test
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18
|
||||
|
||||
- name: Get version
|
||||
id: version
|
||||
run: echo "version=$(cat IRIS_VERSION)" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Build frontend assets
|
||||
run: |
|
||||
npm ci
|
||||
npm run prod
|
||||
|
||||
- name: Build Python sdist
|
||||
run: |
|
||||
pip install --break-system-packages build
|
||||
python -m build --sdist
|
||||
|
||||
- name: Upload sdist to Gitea release
|
||||
continue-on-error: true
|
||||
env:
|
||||
GITEA_TOKEN: ${{ secrets.GITEA }}
|
||||
run: |
|
||||
set -x
|
||||
VERSION=$(cat IRIS_VERSION)
|
||||
echo "Version: ${VERSION}"
|
||||
|
||||
ASSET=$(ls dist/*.tar.gz 2>/dev/null | head -1)
|
||||
echo "Asset: ${ASSET}"
|
||||
if [ -z "$ASSET" ]; then
|
||||
echo "ERROR: no sdist tarball found in dist/"
|
||||
ls -la dist/ 2>/dev/null || echo "dist/ does not exist"
|
||||
exit 1
|
||||
fi
|
||||
if [ ! -f "$ASSET" ]; then
|
||||
echo "ERROR: asset file missing: ${ASSET}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
AUTH="Authorization: token ${GITEA_TOKEN}"
|
||||
API="http://gitea.service:3000/api/v1/repos/secstate/Iris"
|
||||
|
||||
# Delete old release first (by tag lookup), then delete the tag
|
||||
echo "--- Looking up existing release ---"
|
||||
OLD_ID=$(curl -sf "${API}/releases/tags/continuous" \
|
||||
-H "${AUTH}" \
|
||||
| python3 -c "import sys,json;print(json.load(sys.stdin).get('id',''))" 2>/dev/null || echo "")
|
||||
if [ -n "$OLD_ID" ]; then
|
||||
echo "Deleting old release ID=${OLD_ID}"
|
||||
curl -f -X DELETE "${API}/releases/${OLD_ID}" -H "${AUTH}" \
|
||||
-w "\nDELETE release HTTP %{http_code}\n" || echo "Delete release returned non-zero"
|
||||
else
|
||||
echo "No existing release found"
|
||||
fi
|
||||
|
||||
echo "--- Deleting old tag ---"
|
||||
curl -f -X DELETE "${API}/tags/continuous" -H "${AUTH}" \
|
||||
-w "DELETE tag HTTP %{http_code}\n" || echo "Tag delete non-zero (may not exist)"
|
||||
|
||||
echo "--- Creating release ---"
|
||||
RELEASE_ID=$(curl -f -X POST "${API}/releases" \
|
||||
-H "${AUTH}" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"tag_name":"continuous","name":"Continuous build","prerelease":true,"target_commitish":"main"}' \
|
||||
| python3 -c "import sys,json;print(json.load(sys.stdin)['id'])") || {
|
||||
echo "ERROR: failed to create release"
|
||||
exit 1
|
||||
}
|
||||
echo "Created release ID=${RELEASE_ID}"
|
||||
|
||||
echo "--- Uploading asset ---"
|
||||
curl -f -X POST "${API}/releases/${RELEASE_ID}/assets" \
|
||||
-H "${AUTH}" \
|
||||
-F "attachment=@${ASSET}" \
|
||||
-w "UPLOAD asset HTTP %{http_code}\n" >&2 || {
|
||||
echo "ERROR: asset upload failed"
|
||||
exit 1
|
||||
}
|
||||
echo "--- Done ---"
|
||||
|
||||
- name: Copy sdist to server
|
||||
uses: appleboy/scp-action@v0.1.7
|
||||
with:
|
||||
host: mopidy-dev.service
|
||||
username: root
|
||||
key: ${{ secrets.JAIL_KEY }}
|
||||
target: /tmp/iris-deploy/
|
||||
source: dist/
|
||||
|
||||
- name: Install on server
|
||||
uses: appleboy/ssh-action@v1.0.3
|
||||
with:
|
||||
host: mopidy-dev.service
|
||||
username: root
|
||||
key: ${{ secrets.JAIL_KEY }}
|
||||
script: |
|
||||
pip uninstall -y --break-system-packages mopidy-iris
|
||||
pip install --break-system-packages /tmp/iris-deploy/dist/*.tar.gz
|
||||
rm -rf /tmp/iris-deploy
|
||||
service mopidy restart
|
||||
|
||||
- name: Notify deploy success (ntfy)
|
||||
if: success()
|
||||
run: |
|
||||
curl -fsS \
|
||||
-H "Title: Iris deploy success" \
|
||||
-H "Priority: low" \
|
||||
-H "Tags: success,iris,deploy" \
|
||||
-H "Actions: view, View changes, ${{ gitea.server_url }}/${{ gitea.repository }}/commit/${{ gitea.sha }}; view, View build, ${{ gitea.server_url }}/${{ gitea.repository }}/actions/runs/${{ gitea.run_id }}" \
|
||||
-d "🚀 Deploy succeeded: ${{ gitea.ref_name }} (${{ gitea.sha }})" \
|
||||
https://ntfy.unbl.ink/drone
|
||||
|
||||
- name: Notify deploy failure (ntfy)
|
||||
if: failure()
|
||||
run: |
|
||||
curl -fsS \
|
||||
-H "Title: Iris deploy failure" \
|
||||
-H "Priority: high" \
|
||||
-H "Tags: failure,iris,deploy" \
|
||||
-H "Actions: view, View changes, ${{ gitea.server_url }}/${{ gitea.repository }}/commit/${{ gitea.sha }}; view, View build, ${{ gitea.server_url }}/${{ gitea.repository }}/actions/runs/${{ gitea.run_id }}" \
|
||||
-d "💥 Deploy failed: ${{ gitea.ref_name }} (${{ gitea.sha }})" \
|
||||
https://ntfy.unbl.ink/drone
|
||||
4
.gitignore
vendored
@ -1,6 +1,8 @@
|
||||
/node_modules/
|
||||
/Mopidy_Iris.egg-info/
|
||||
/mopidy_iris/static/*
|
||||
/mopidy_iris/static/*.map
|
||||
/mopidy_iris/static/app.js
|
||||
/mopidy_iris/static/app.css
|
||||
public_html
|
||||
/dist/
|
||||
/build/
|
||||
|
||||
@ -12,6 +12,14 @@ Built and maintained by James Barnsley.
|
||||
.. image:: https://img.shields.io/badge/donate-paypal-blue.svg?style=flat-square
|
||||
:target: https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=james%40barnsley%2enz&lc=NZ&item_name=James%20Barnsley¤cy_code=USD&bn=PP%2dDonationsBF%3abtn_donate_LG%2egif%3aNonHosted
|
||||
|
||||
Fork notes (by powellc)
|
||||
**********
|
||||
|
||||
- Add support for mopidy-smartlists
|
||||
- Add support for filtering the root Album view by release date
|
||||
- Add default "Added" sorting to the drop down sort menu
|
||||
- General test clean up
|
||||
|
||||
Features
|
||||
********
|
||||
|
||||
|
||||
131
__tests__/components/PlaybackControls.test.js
Normal file
@ -0,0 +1,131 @@
|
||||
import React from 'react';
|
||||
import { act } from 'react-test-renderer';
|
||||
import { render } from '../test-wrapper';
|
||||
import PlaybackControls from '../../src/js/components/PlaybackControls';
|
||||
import state from '../state';
|
||||
|
||||
const mockState = {
|
||||
...state,
|
||||
mopidy: {
|
||||
...state.mopidy,
|
||||
time_position: 0,
|
||||
volume: 50,
|
||||
mute: false,
|
||||
play_state: 'stopped',
|
||||
consume: false,
|
||||
random: false,
|
||||
repeat: false,
|
||||
host: 'localhost',
|
||||
port: '6680',
|
||||
ssl: false,
|
||||
},
|
||||
ui: {
|
||||
...state.ui,
|
||||
touch_enabled: false,
|
||||
sidebar_open: false,
|
||||
slim_mode: false,
|
||||
},
|
||||
core: {
|
||||
...state.core,
|
||||
streamTitle: null,
|
||||
current_track: null,
|
||||
next_track_uri: null,
|
||||
},
|
||||
};
|
||||
|
||||
jest.mock('react-redux', () => ({
|
||||
useSelector: jest.fn().mockImplementation((func) => func(mockState)),
|
||||
useDispatch: () => jest.fn(),
|
||||
}));
|
||||
|
||||
jest.mock('../../src/js/components/Icon', () => 'Icon');
|
||||
jest.mock('../../src/js/components/Link', () => 'Link');
|
||||
jest.mock('../../src/js/components/Thumbnail', () => 'Thumbnail');
|
||||
jest.mock('../../src/js/components/LinksSentence', () => 'LinksSentence');
|
||||
jest.mock('../../src/js/components/Fields/ProgressSlider', () => 'ProgressSlider');
|
||||
jest.mock('../../src/js/components/Fields/VolumeControl', () => 'VolumeControl');
|
||||
jest.mock('../../src/js/components/Fields/MuteControl', () => 'MuteControl');
|
||||
jest.mock('../../src/js/components/Fields/OutputControl', () => 'OutputControl');
|
||||
|
||||
function findSmartQueueButton(renderer) {
|
||||
const buttons = renderer.root.findAllByType('button');
|
||||
return buttons.find((btn) => {
|
||||
if (!btn.props.children) return false;
|
||||
const children = Array.isArray(btn.props.children)
|
||||
? btn.props.children
|
||||
: [btn.props.children];
|
||||
return children.some(
|
||||
(child) => child.props && child.props.name === 'lightbulb_outline',
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
describe('<PlaybackControls />', () => {
|
||||
beforeEach(() => {
|
||||
localStorage.clear();
|
||||
jest.clearAllMocks();
|
||||
global.fetch = jest.fn(() => Promise.resolve({ ok: true }));
|
||||
});
|
||||
|
||||
it('should render correctly', () => {
|
||||
const result = render(<PlaybackControls />).toJSON();
|
||||
expect(result).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should render smart queue button in settings section', () => {
|
||||
const renderer = render(<PlaybackControls />);
|
||||
expect(findSmartQueueButton(renderer)).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should have inactive smart queue button by default', () => {
|
||||
const renderer = render(<PlaybackControls />);
|
||||
const btn = findSmartQueueButton(renderer);
|
||||
expect(btn.props.className).not.toContain('control--active');
|
||||
});
|
||||
|
||||
it('should toggle active class on click and call fetch', () => {
|
||||
const renderer = render(<PlaybackControls />);
|
||||
const btn = findSmartQueueButton(renderer);
|
||||
act(() => { btn.props.onClick(); });
|
||||
|
||||
const newBtn = findSmartQueueButton(renderer);
|
||||
expect(newBtn.props.className).toContain('control--active');
|
||||
expect(global.fetch).toHaveBeenCalledTimes(1);
|
||||
expect(global.fetch).toHaveBeenCalledWith(
|
||||
'http://localhost:6680/smartplaylists/smart-queue',
|
||||
{
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ enabled: true }),
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
it('should send enabled=false on second click', () => {
|
||||
const renderer = render(<PlaybackControls />);
|
||||
let btn = findSmartQueueButton(renderer);
|
||||
act(() => { btn.props.onClick(); });
|
||||
|
||||
btn = findSmartQueueButton(renderer);
|
||||
act(() => { btn.props.onClick(); });
|
||||
|
||||
expect(global.fetch).toHaveBeenCalledTimes(2);
|
||||
expect(global.fetch).toHaveBeenLastCalledWith(
|
||||
'http://localhost:6680/smartplaylists/smart-queue',
|
||||
{
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ enabled: false }),
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
it('should restore smart queue state from localStorage', () => {
|
||||
localStorage.setItem('smartQueue', 'true');
|
||||
const renderer = render(<PlaybackControls />);
|
||||
const btn = findSmartQueueButton(renderer);
|
||||
expect(btn.props.className).toContain('control--active');
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
284
__tests__/components/__snapshots__/PlaybackControls.test.js.snap
Normal file
@ -0,0 +1,284 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`<PlaybackControls /> should render correctly 1`] = `
|
||||
<div
|
||||
className="playback-controls"
|
||||
data-qa-file="PlaybackControls"
|
||||
data-qa-node="div"
|
||||
>
|
||||
<div
|
||||
className="playback-controls__background"
|
||||
data-qa-file="PlaybackControls"
|
||||
data-qa-node="div"
|
||||
/>
|
||||
<div
|
||||
className="current-track__wrapper"
|
||||
data-qa-file="PlaybackControls"
|
||||
data-qa-node="div"
|
||||
>
|
||||
<div
|
||||
className="current-track"
|
||||
data-qa-file="PlaybackControls"
|
||||
data-qa-node="div"
|
||||
tabIndex="-1"
|
||||
>
|
||||
<Link
|
||||
className="thumbnail-wrapper"
|
||||
data-qa-file="PlaybackControls"
|
||||
data-qa-node="Link"
|
||||
tabIndex="-1"
|
||||
to="/modal/kiosk-mode"
|
||||
>
|
||||
<Thumbnail
|
||||
data-qa-file="PlaybackControls"
|
||||
data-qa-node="Thumbnail"
|
||||
size="small"
|
||||
type="track"
|
||||
/>
|
||||
</Link>
|
||||
<div
|
||||
className="text"
|
||||
data-qa-file="PlaybackControls"
|
||||
data-qa-node="div"
|
||||
>
|
||||
<div
|
||||
className="title"
|
||||
data-qa-file="PlaybackControls"
|
||||
data-qa-node="div"
|
||||
>
|
||||
|
||||
</div>
|
||||
<div
|
||||
className="artist"
|
||||
data-qa-file="PlaybackControls"
|
||||
data-qa-node="div"
|
||||
>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<section
|
||||
className="playback"
|
||||
data-qa-file="PlaybackControls"
|
||||
data-qa-node="section"
|
||||
>
|
||||
<button
|
||||
className="control previous"
|
||||
data-qa-file="PlaybackControls"
|
||||
data-qa-node="button"
|
||||
onClick={[Function]}
|
||||
type="button"
|
||||
>
|
||||
<Icon
|
||||
data-qa-file="PlaybackControls"
|
||||
data-qa-node="Icon"
|
||||
name="navigate_before"
|
||||
type="material"
|
||||
/>
|
||||
</button>
|
||||
<button
|
||||
className="control play"
|
||||
data-qa-file="PlaybackControls"
|
||||
data-qa-node="button"
|
||||
onClick={[Function]}
|
||||
type="button"
|
||||
>
|
||||
<Icon
|
||||
data-qa-file="PlaybackControls"
|
||||
data-qa-node="Icon"
|
||||
name="play_circle_filled"
|
||||
type="material"
|
||||
/>
|
||||
</button>
|
||||
<button
|
||||
className="control next"
|
||||
data-qa-file="PlaybackControls"
|
||||
data-qa-node="button"
|
||||
onClick={[Function]}
|
||||
type="button"
|
||||
>
|
||||
<Icon
|
||||
data-qa-file="PlaybackControls"
|
||||
data-qa-node="Icon"
|
||||
name="navigate_next"
|
||||
type="material"
|
||||
/>
|
||||
</button>
|
||||
</section>
|
||||
<section
|
||||
className="progress"
|
||||
data-qa-file="PlaybackControls"
|
||||
data-qa-node="section"
|
||||
>
|
||||
<div
|
||||
className="time time--current"
|
||||
data-qa-file="PlaybackControls"
|
||||
data-qa-node="div"
|
||||
>
|
||||
-
|
||||
</div>
|
||||
<ProgressSlider
|
||||
data-qa-file="PlaybackControls"
|
||||
data-qa-node="ProgressSlider"
|
||||
playbackPosition={0}
|
||||
/>
|
||||
<div
|
||||
className="time time--total"
|
||||
data-qa-file="PlaybackControls"
|
||||
data-qa-node="div"
|
||||
>
|
||||
-
|
||||
</div>
|
||||
</section>
|
||||
<section
|
||||
className="settings"
|
||||
data-qa-file="PlaybackControls"
|
||||
data-qa-node="section"
|
||||
>
|
||||
<button
|
||||
className="control tooltip"
|
||||
data-qa-file="PlaybackControls"
|
||||
data-qa-node="button"
|
||||
onClick={[Function]}
|
||||
type="button"
|
||||
>
|
||||
<Icon
|
||||
data-qa-file="PlaybackControls"
|
||||
data-qa-node="Icon"
|
||||
name="restaurant"
|
||||
type="material"
|
||||
/>
|
||||
<span
|
||||
className="tooltip__content"
|
||||
data-qa-file="PlaybackControls"
|
||||
data-qa-node="span"
|
||||
>
|
||||
Consume
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
className="control tooltip"
|
||||
data-qa-file="PlaybackControls"
|
||||
data-qa-node="button"
|
||||
onClick={[Function]}
|
||||
type="button"
|
||||
>
|
||||
<Icon
|
||||
data-qa-file="PlaybackControls"
|
||||
data-qa-node="Icon"
|
||||
name="lightbulb_outline"
|
||||
type="material"
|
||||
/>
|
||||
<span
|
||||
className="tooltip__content"
|
||||
data-qa-file="PlaybackControls"
|
||||
data-qa-node="span"
|
||||
>
|
||||
Smart Queue
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
className="control tooltip"
|
||||
data-qa-file="PlaybackControls"
|
||||
data-qa-node="button"
|
||||
onClick={[Function]}
|
||||
type="button"
|
||||
>
|
||||
<Icon
|
||||
data-qa-file="PlaybackControls"
|
||||
data-qa-node="Icon"
|
||||
name="shuffle"
|
||||
type="material"
|
||||
/>
|
||||
<span
|
||||
className="tooltip__content"
|
||||
data-qa-file="PlaybackControls"
|
||||
data-qa-node="span"
|
||||
>
|
||||
Shuffle
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
className="control tooltip"
|
||||
data-qa-file="PlaybackControls"
|
||||
data-qa-node="button"
|
||||
onClick={[Function]}
|
||||
type="button"
|
||||
>
|
||||
<Icon
|
||||
data-qa-file="PlaybackControls"
|
||||
data-qa-node="Icon"
|
||||
name="repeat"
|
||||
type="material"
|
||||
/>
|
||||
<span
|
||||
className="tooltip__content"
|
||||
data-qa-file="PlaybackControls"
|
||||
data-qa-node="span"
|
||||
>
|
||||
Repeat
|
||||
</span>
|
||||
</button>
|
||||
<OutputControl
|
||||
data-qa-file="PlaybackControls"
|
||||
data-qa-node="OutputControl"
|
||||
/>
|
||||
</section>
|
||||
<section
|
||||
className="volume"
|
||||
data-qa-file="PlaybackControls"
|
||||
data-qa-node="section"
|
||||
>
|
||||
<MuteControl
|
||||
data-qa-file="PlaybackControls"
|
||||
data-qa-node="MuteControl"
|
||||
mute={false}
|
||||
onMuteChange={[Function]}
|
||||
/>
|
||||
<VolumeControl
|
||||
data-qa-file="PlaybackControls"
|
||||
data-qa-node="VolumeControl"
|
||||
mute={false}
|
||||
onVolumeChange={[Function]}
|
||||
scrollWheel={true}
|
||||
volume={50}
|
||||
/>
|
||||
</section>
|
||||
<section
|
||||
className="triggers"
|
||||
data-qa-file="PlaybackControls"
|
||||
data-qa-node="section"
|
||||
>
|
||||
<button
|
||||
className="control expanded-controls"
|
||||
data-qa-file="PlaybackControls"
|
||||
data-qa-node="button"
|
||||
onClick={[Function]}
|
||||
type="button"
|
||||
>
|
||||
<Icon
|
||||
data-qa-file="PlaybackControls"
|
||||
data-qa-node="Icon"
|
||||
name="expand_less"
|
||||
type="material"
|
||||
/>
|
||||
</button>
|
||||
<button
|
||||
className="control sidebar-toggle"
|
||||
data-qa-file="PlaybackControls"
|
||||
data-qa-node="button"
|
||||
onClick={[Function]}
|
||||
type="button"
|
||||
>
|
||||
<Icon
|
||||
className="open"
|
||||
data-qa-file="PlaybackControls"
|
||||
data-qa-node="Icon"
|
||||
name="menu"
|
||||
type="material"
|
||||
/>
|
||||
</button>
|
||||
</section>
|
||||
</div>
|
||||
`;
|
||||
107
__tests__/util/arrays.test.js
Normal file
@ -0,0 +1,107 @@
|
||||
import { sortItems } from '../../src/js/util/arrays';
|
||||
|
||||
describe('sortItems', () => {
|
||||
describe('date sorting', () => {
|
||||
it('should prefer a date embedded in the filename over the tag date', () => {
|
||||
const tracks = [
|
||||
{
|
||||
name: 'Talk Python',
|
||||
uri: 'file:///media/podcasts/563-2026-09-22-EVE-Online.mp3',
|
||||
release_date: '2023-10-13',
|
||||
},
|
||||
{
|
||||
name: 'Up First',
|
||||
uri: 'file:///media/podcasts/2026-09-01_Up%20First.mp3',
|
||||
release_date: '2026-09-01',
|
||||
},
|
||||
];
|
||||
|
||||
expect(sortItems(tracks, 'date').map((track) => track.name)).toEqual([
|
||||
'Up First',
|
||||
'Talk Python',
|
||||
]);
|
||||
});
|
||||
|
||||
it('should fall back to the tag date when the filename has no date', () => {
|
||||
const tracks = [
|
||||
{
|
||||
name: 'Newer',
|
||||
uri: 'spotify:track:newer',
|
||||
release_date: '2001-05-01',
|
||||
},
|
||||
{
|
||||
name: 'Older',
|
||||
uri: 'spotify:track:older',
|
||||
release_date: '1999-01-01',
|
||||
},
|
||||
];
|
||||
|
||||
expect(sortItems(tracks, 'date').map((track) => track.name)).toEqual([
|
||||
'Older',
|
||||
'Newer',
|
||||
]);
|
||||
});
|
||||
|
||||
it('should sort year-only tag dates within their year', () => {
|
||||
const tracks = [
|
||||
{
|
||||
name: 'Year only',
|
||||
uri: 'spotify:track:year',
|
||||
release_date: '2026',
|
||||
},
|
||||
{
|
||||
name: 'Previous year',
|
||||
uri: 'spotify:track:previous',
|
||||
release_date: '2025-12-31',
|
||||
},
|
||||
];
|
||||
|
||||
expect(sortItems(tracks, 'date').map((track) => track.name)).toEqual([
|
||||
'Previous year',
|
||||
'Year only',
|
||||
]);
|
||||
});
|
||||
|
||||
it('should sort tracks sharing a date by album and track number', () => {
|
||||
const tracks = [
|
||||
{
|
||||
name: 'Second',
|
||||
uri: 'file:///media/podcasts/2026-09-22_second.mp3',
|
||||
album: { name: 'Podcast' },
|
||||
track_number: 2,
|
||||
},
|
||||
{
|
||||
name: 'First',
|
||||
uri: 'file:///media/podcasts/2026-09-22_first.mp3',
|
||||
album: { name: 'Podcast' },
|
||||
track_number: 1,
|
||||
},
|
||||
];
|
||||
|
||||
expect(sortItems(tracks, 'date').map((track) => track.name)).toEqual([
|
||||
'First',
|
||||
'Second',
|
||||
]);
|
||||
});
|
||||
|
||||
it('should reverse the order', () => {
|
||||
const tracks = [
|
||||
{
|
||||
name: 'Talk Python',
|
||||
uri: 'file:///media/podcasts/563-2026-09-22-EVE-Online.mp3',
|
||||
release_date: '2023-10-13',
|
||||
},
|
||||
{
|
||||
name: 'Up First',
|
||||
uri: 'file:///media/podcasts/2026-09-01_Up%20First.mp3',
|
||||
release_date: '2026-09-01',
|
||||
},
|
||||
];
|
||||
|
||||
expect(sortItems(tracks, 'date', true).map((track) => track.name)).toEqual([
|
||||
'Talk Python',
|
||||
'Up First',
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -3,7 +3,7 @@ import {
|
||||
decodeUri,
|
||||
} from '../../src/js/util/format';
|
||||
|
||||
const encoded = 'c3BvdGlmeTphbGJ1bTpodHRwOi8vdGVzdC5jb20vMTIzIUAjJCVeJltdOzw+Lz8i4oCU4oCTLcOhw4HDoMOAw6LDgsOkw4TDo8ODw6XDhcOmw4bDp8OHw6nDicOow4jDqsOKw6vDi8Otw43DrMOMw67DjsOvw4/DscORw7PDk8Oyw5LDtMOUw7bDlsO1w5XDuMOYxZPFksOfw7rDmsO5w5nDu8Obw7zDnCAubXAz';
|
||||
const encoded = 'c3BvdGlmeTphbGJ1bTpodHRwOi8vdGVzdC5jb20vMTIzIUAjJCVeJltdOzw-Lz8i4oCU4oCTLcOhw4HDoMOAw6LDgsOkw4TDo8ODw6XDhcOmw4bDp8OHw6nDicOow4jDqsOKw6vDi8Otw43DrMOMw67DjsOvw4_DscORw7PDk8Oyw5LDtMOUw7bDlsO1w5XDuMOYxZPFksOfw7rDmsO5w5nDu8Obw7zDnCAubXAz';
|
||||
const decoded = 'spotify:album:http://test.com/123!@#$%^&[];<>/?"—–-áÁàÀâÂäÄãÃåÅæÆçÇéÉèÈêÊëËíÍìÌîÎïÏñÑóÓòÒôÔöÖõÕøØœŒßúÚùÙûÛüÜ .mp3';
|
||||
|
||||
describe('encodeUri', () => {
|
||||
|
||||
@ -159,7 +159,7 @@ describe('buildLink', () => {
|
||||
it('should handle special characters', () => {
|
||||
let link = helpers.buildLink('spotify:album:http://test.com/123!@#$%^&[];<>/?" .mp3');
|
||||
expect(typeof (link)).toBe('string');
|
||||
expect(link).toBe('/album/c3BvdGlmeTphbGJ1bTpodHRwOi8vdGVzdC5jb20vMTIzIUAjJCVeJltdOzw+Lz8iIC5tcDM=');
|
||||
expect(link).toBe('/album/c3BvdGlmeTphbGJ1bTpodHRwOi8vdGVzdC5jb20vMTIzIUAjJCVeJltdOzw-Lz8iIC5tcDM=');
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
20
justfile
Normal file
@ -0,0 +1,20 @@
|
||||
default:
|
||||
@just --list
|
||||
|
||||
# Build production webpack bundle
|
||||
build-prod:
|
||||
npm run prod
|
||||
|
||||
# Stage the built static files
|
||||
stage-static:
|
||||
git add mopidy_iris/static/
|
||||
|
||||
# Release: build, commit all changes, tag, and push
|
||||
release:
|
||||
npm run prod
|
||||
git add -A
|
||||
version=$$(cat IRIS_VERSION) && \
|
||||
git commit -m "Buildout $$version" && \
|
||||
git tag -a "$$version" -m "Buildout $$version" && \
|
||||
git push && \
|
||||
git push origin "$$version"
|
||||
4
mopidy_iris/static/app.min.css
vendored
Normal file
2
mopidy_iris/static/app.min.js
vendored
Normal file
166
mopidy_iris/static/app.min.js.LICENSE.txt
Normal file
@ -0,0 +1,166 @@
|
||||
/*!
|
||||
localForage -- Offline Storage, Improved
|
||||
Version 1.10.0
|
||||
https://localforage.github.io/localForage
|
||||
(c) 2013-2017 Mozilla, Apache License 2.0
|
||||
*/
|
||||
|
||||
/*!
|
||||
* Sizzle CSS Selector Engine v2.3.6
|
||||
* https://sizzlejs.com/
|
||||
*
|
||||
* Copyright JS Foundation and other contributors
|
||||
* Released under the MIT license
|
||||
* https://js.foundation/
|
||||
*
|
||||
* Date: 2021-02-16
|
||||
*/
|
||||
|
||||
/*!
|
||||
* is-plain-object <https://github.com/jonschlinkert/is-plain-object>
|
||||
*
|
||||
* Copyright (c) 2014-2017, Jon Schlinkert.
|
||||
* Released under the MIT License.
|
||||
*/
|
||||
|
||||
/*!
|
||||
* jQuery JavaScript Library v3.6.0
|
||||
* https://jquery.com/
|
||||
*
|
||||
* Includes Sizzle.js
|
||||
* https://sizzlejs.com/
|
||||
*
|
||||
* Copyright OpenJS Foundation and other contributors
|
||||
* Released under the MIT license
|
||||
* https://jquery.org/license
|
||||
*
|
||||
* Date: 2021-03-02T17:08Z
|
||||
*/
|
||||
|
||||
/**
|
||||
* @license
|
||||
* Lodash <https://lodash.com/>
|
||||
* Copyright OpenJS Foundation and other contributors <https://openjsf.org/>
|
||||
* Released under MIT license <https://lodash.com/license>
|
||||
* Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
|
||||
* Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
|
||||
*/
|
||||
|
||||
/**
|
||||
* @license React
|
||||
* react-dom.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @license React
|
||||
* react-is.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @license React
|
||||
* react-jsx-runtime.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @license React
|
||||
* react.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @license React
|
||||
* scheduler.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @license React
|
||||
* use-sync-external-store-shim.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @license React
|
||||
* use-sync-external-store-shim/with-selector.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/**
|
||||
* React Router DOM v6.3.0
|
||||
*
|
||||
* Copyright (c) Remix Software Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE.md file in the root directory of this source tree.
|
||||
*
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
/**
|
||||
* React Router v6.3.0
|
||||
*
|
||||
* Copyright (c) Remix Software Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE.md file in the root directory of this source tree.
|
||||
*
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
/**
|
||||
* [js-sha256]{@link https://github.com/emn178/js-sha256}
|
||||
*
|
||||
* @version 0.9.0
|
||||
* @author Chen, Yi-Cyuan [emn178@gmail.com]
|
||||
* @copyright Chen, Yi-Cyuan 2014-2017
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
/** @license React v16.13.1
|
||||
* react-is.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/**!
|
||||
* hotkeys-js v3.9.3
|
||||
* A simple micro-library for defining and dispatching keyboard shortcuts. It has no dependencies.
|
||||
*
|
||||
* Copyright (c) 2022 kenny wong <wowohoo@qq.com>
|
||||
* http://jaywcjlove.github.io/hotkeys
|
||||
* Licensed under the MIT license
|
||||
*/
|
||||
BIN
mopidy_iris/static/assets/MaterialIcons-Regular.eot
Normal file
BIN
mopidy_iris/static/assets/MaterialIcons-Regular.ttf
Normal file
BIN
mopidy_iris/static/assets/MaterialIcons-Regular.woff
Normal file
BIN
mopidy_iris/static/assets/MaterialIcons-Regular.woff2
Normal file
12
mopidy_iris/static/assets/app-icon-invert.svg
Normal file
@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 25.2.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="_x31_92b1ddc-b58c-4510-a73c-0fc2a95ef212"
|
||||
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 192 192"
|
||||
style="enable-background:new 0 0 192 192;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#08D58F;}
|
||||
.st1{fill:#FFFFFF;}
|
||||
</style>
|
||||
<rect class="st0" width="192" height="192"/>
|
||||
<path class="st1" d="M86.4,124.1l-46.7,45.6V22.3l46.7,45.6V124.1z M86.4,22.3v22.3l53,50.9l-53,52v21.2l76.3-73.2L86.4,22.3z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 637 B |
1
mopidy_iris/static/assets/app-icon.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg id="192b1ddc-b58c-4510-a73c-0fc2a95ef212" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 192 192"><title>app-icon</title><path d="M81.5,129.23,26.33,183.14V8.86L81.5,62.77Zm0-120.37V35.19l62.7,60.18L81.5,156.81v25.08l90.28-86.52Z" style="fill:#08d58f"/></svg>
|
||||
|
After Width: | Height: | Size: 285 B |
BIN
mopidy_iris/static/assets/app-icon_114.png
Normal file
|
After Width: | Height: | Size: 962 B |
BIN
mopidy_iris/static/assets/app-icon_120.png
Normal file
|
After Width: | Height: | Size: 1010 B |
BIN
mopidy_iris/static/assets/app-icon_144.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
mopidy_iris/static/assets/app-icon_152.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
mopidy_iris/static/assets/app-icon_180.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
mopidy_iris/static/assets/app-icon_192.png
Normal file
|
After Width: | Height: | Size: 7.8 KiB |
BIN
mopidy_iris/static/assets/app-icon_256.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
mopidy_iris/static/assets/app-icon_512.png
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
mopidy_iris/static/assets/app-icon_57.png
Normal file
|
After Width: | Height: | Size: 606 B |
BIN
mopidy_iris/static/assets/app-icon_60.png
Normal file
|
After Width: | Height: | Size: 633 B |
BIN
mopidy_iris/static/assets/app-icon_64.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
mopidy_iris/static/assets/app-icon_72.png
Normal file
|
After Width: | Height: | Size: 694 B |
BIN
mopidy_iris/static/assets/app-icon_76.png
Normal file
|
After Width: | Height: | Size: 723 B |
BIN
mopidy_iris/static/assets/backgrounds/browse-albums.jpg
Normal file
|
After Width: | Height: | Size: 55 KiB |
BIN
mopidy_iris/static/assets/backgrounds/browse-artists.jpg
Normal file
|
After Width: | Height: | Size: 26 KiB |
BIN
mopidy_iris/static/assets/backgrounds/browse-default.jpg
Normal file
|
After Width: | Height: | Size: 41 KiB |
BIN
mopidy_iris/static/assets/backgrounds/browse-dirble.jpg
Normal file
|
After Width: | Height: | Size: 31 KiB |
BIN
mopidy_iris/static/assets/backgrounds/browse-folders.jpg
Normal file
|
After Width: | Height: | Size: 41 KiB |
BIN
mopidy_iris/static/assets/backgrounds/browse-google.jpg
Normal file
|
After Width: | Height: | Size: 26 KiB |
BIN
mopidy_iris/static/assets/backgrounds/browse-hearthis.jpg
Normal file
|
After Width: | Height: | Size: 44 KiB |
BIN
mopidy_iris/static/assets/backgrounds/browse-itunes.jpg
Normal file
|
After Width: | Height: | Size: 70 KiB |
BIN
mopidy_iris/static/assets/backgrounds/browse-jellyfin.jpg
Normal file
|
After Width: | Height: | Size: 34 KiB |
BIN
mopidy_iris/static/assets/backgrounds/browse-mixcloud.jpg
Normal file
|
After Width: | Height: | Size: 53 KiB |
BIN
mopidy_iris/static/assets/backgrounds/browse-podcasts.jpg
Normal file
|
After Width: | Height: | Size: 83 KiB |
BIN
mopidy_iris/static/assets/backgrounds/browse-somafm.jpg
Normal file
|
After Width: | Height: | Size: 41 KiB |
BIN
mopidy_iris/static/assets/backgrounds/browse-soundcloud.jpg
Normal file
|
After Width: | Height: | Size: 47 KiB |
BIN
mopidy_iris/static/assets/backgrounds/browse-spotify.jpg
Normal file
|
After Width: | Height: | Size: 37 KiB |
BIN
mopidy_iris/static/assets/backgrounds/browse-tidal.jpg
Normal file
|
After Width: | Height: | Size: 27 KiB |
BIN
mopidy_iris/static/assets/backgrounds/browse-tunein.jpg
Normal file
|
After Width: | Height: | Size: 30 KiB |
BIN
mopidy_iris/static/assets/backgrounds/browse-tunigo.jpg
Normal file
|
After Width: | Height: | Size: 47 KiB |
BIN
mopidy_iris/static/assets/backgrounds/browse-youtube.jpg
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
mopidy_iris/static/assets/backgrounds/discover.jpg
Normal file
|
After Width: | Height: | Size: 343 KiB |
BIN
mopidy_iris/static/assets/backgrounds/settings.jpg
Normal file
|
After Width: | Height: | Size: 91 KiB |
1
mopidy_iris/static/assets/blur.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg"> <filter id="blur"> <feGaussianBlur stdDeviation="10" /> </filter> </svg>
|
||||
|
After Width: | Height: | Size: 127 B |
BIN
mopidy_iris/static/assets/favicon.ico
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
mopidy_iris/static/assets/favicon.png
Normal file
|
After Width: | Height: | Size: 5.5 KiB |
BIN
mopidy_iris/static/assets/favicon_error.png
Normal file
|
After Width: | Height: | Size: 5.4 KiB |
BIN
mopidy_iris/static/assets/favicon_paused.png
Normal file
|
After Width: | Height: | Size: 4.8 KiB |
BIN
mopidy_iris/static/assets/fontawesome-webfont.eot
Normal file
2671
mopidy_iris/static/assets/fontawesome-webfont.svg
Normal file
|
After Width: | Height: | Size: 434 KiB |
BIN
mopidy_iris/static/assets/fontawesome-webfont.ttf
Normal file
BIN
mopidy_iris/static/assets/fontawesome-webfont.woff
Normal file
BIN
mopidy_iris/static/assets/fontawesome-webfont.woff2
Normal file
BIN
mopidy_iris/static/assets/fonts/FontAwesome.otf
Normal file
BIN
mopidy_iris/static/assets/fonts/MaterialIcons-Regular.eot
Normal file
BIN
mopidy_iris/static/assets/fonts/MaterialIcons-Regular.ttf
Normal file
BIN
mopidy_iris/static/assets/fonts/MaterialIcons-Regular.woff
Normal file
BIN
mopidy_iris/static/assets/fonts/MaterialIcons-Regular.woff2
Normal file
BIN
mopidy_iris/static/assets/fonts/fontawesome-webfont.eot
Normal file
2671
mopidy_iris/static/assets/fonts/fontawesome-webfont.svg
Normal file
|
After Width: | Height: | Size: 434 KiB |
BIN
mopidy_iris/static/assets/fonts/fontawesome-webfont.ttf
Normal file
BIN
mopidy_iris/static/assets/fonts/fontawesome-webfont.woff
Normal file
BIN
mopidy_iris/static/assets/fonts/fontawesome-webfont.woff2
Normal file
BIN
mopidy_iris/static/assets/fonts/iris.eot
Normal file
45
mopidy_iris/static/assets/fonts/iris.svg
Normal file
@ -0,0 +1,45 @@
|
||||
<?xml version="1.0" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
|
||||
<svg xmlns="http://www.w3.org/2000/svg">
|
||||
<metadata>Generated by IcoMoon</metadata>
|
||||
<defs>
|
||||
<font id="icomoon" horiz-adv-x="1024">
|
||||
<font-face units-per-em="1024" ascent="960" descent="-64" />
|
||||
<missing-glyph horiz-adv-x="1024" />
|
||||
<glyph unicode=" " horiz-adv-x="512" d="" />
|
||||
<glyph unicode="" glyph-name="back" d="M256 704h85.333v-512h-85.333v512zM405.333 448l362.667-256v512l-362.667-256zM682.667 356.693l-129.28 91.307 129.28 91.307v-182.613z" />
|
||||
<glyph unicode="" glyph-name="broadcast" d="M512 364.8c-44.8 0-83.2 38.4-83.2 83.2s38.4 83.2 83.2 83.2 83.2-38.4 83.2-83.2-38.4-83.2-83.2-83.2zM614.4 236.8c-12.8 0-32 6.4-38.4 19.2-12.8 19.2-6.4 51.2 12.8 64 44.8 25.6 70.4 76.8 70.4 128s-25.6 102.4-70.4 128c-19.2 12.8-25.6 38.4-12.8 64 12.8 19.2 38.4 25.6 64 12.8 70.4-44.8 115.2-121.6 115.2-204.8s-44.8-160-115.2-204.8c-6.4 0-19.2-6.4-25.6-6.4zM409.6 236.8c-6.4 0-19.2 0-25.6 6.4-70.4 44.8-108.8 121.6-108.8 204.8s44.8 160 115.2 204.8c19.2 12.8 44.8 6.4 57.6-12.8s6.4-51.2-12.8-64c-44.8-25.6-70.4-76.8-70.4-128s25.6-102.4 70.4-128c19.2-12.8 25.6-38.4 12.8-64-6.4-6.4-25.6-19.2-38.4-19.2zM736 134.4c-12.8 0-25.6 6.4-32 19.2-12.8 19.2-12.8 44.8 6.4 64 70.4 57.6 115.2 147.2 115.2 236.8s-38.4 179.2-115.2 236.8c-19.2 12.8-19.2 44.8-6.4 64s44.8 19.2 64 6.4c89.6-76.8 147.2-185.6 147.2-307.2s-51.2-230.4-147.2-307.2c-12.8-12.8-19.2-12.8-32-12.8zM288 128c-12.8 0-19.2 6.4-25.6 12.8-96 76.8-147.2 185.6-147.2 307.2s51.2 230.4 147.2 307.2c12.8 19.2 44.8 12.8 57.6-6.4s12.8-44.8-6.4-64c-70.4-57.6-108.8-140.8-108.8-236.8s44.8-179.2 115.2-236.8c19.2-12.8 19.2-44.8 6.4-64-12.8-12.8-25.6-19.2-38.4-19.2z" />
|
||||
<glyph unicode="" glyph-name="cd" d="M512 915.2c-256 0-467.2-211.2-467.2-467.2s211.2-467.2 467.2-467.2 467.2 211.2 467.2 467.2c0 256-211.2 467.2-467.2 467.2zM512 537.6c51.2 0 89.6-38.4 89.6-89.6s-38.4-89.6-89.6-89.6-89.6 38.4-89.6 89.6 38.4 89.6 89.6 89.6zM864 588.8l-185.6-76.8c-19.2 44.8-51.2 83.2-96 102.4l83.2 179.2c89.6-38.4 160-115.2 198.4-204.8zM160 313.6l185.6 70.4c19.2-44.8 51.2-83.2 96-102.4l-83.2-179.2c-89.6 44.8-160 115.2-198.4 211.2z" />
|
||||
<glyph unicode="" glyph-name="chevron-left" d="M396.8 518.4l364.8 364.8c25.6 25.6 25.6 57.6 0 83.2s-64 25.6-83.2 0l-409.6-409.6c-12.8-12.8-19.2-25.6-19.2-38.4s6.4-32 19.2-44.8l409.6-409.6c12.8-12.8 25.6-19.2 44.8-19.2s32 6.4 44.8 19.2c25.6 25.6 25.6 57.6 0 83.2l-371.2 371.2z" />
|
||||
<glyph unicode="" glyph-name="chevron-right" d="M761.6 492.8l-409.6 409.6c-25.6 25.6-57.6 25.6-83.2 0s-25.6-57.6 0-83.2l364.8-364.8-364.8-364.8c-25.6-25.6-25.6-57.6 0-83.2 12.8-12.8 25.6-19.2 44.8-19.2s32 6.4 44.8 19.2l409.6 409.6c12.8 12.8 19.2 25.6 19.2 44.8s-19.2 19.2-25.6 32z" />
|
||||
<glyph unicode="" glyph-name="close" d="M921.6 816.64l-40.96 40.96-368.64-368.64-368.64 368.64-40.96-40.96 368.64-368.64-368.64-368.64 40.96-40.96 368.64 368.64 368.64-368.64 40.96 40.96-368.64 368.64z" />
|
||||
<glyph unicode="" glyph-name="cog" d="M829.013 406.187c1.707 13.653 2.987 27.307 2.987 41.813s-1.28 28.16-2.987 41.813l90.027 70.4c8.107 6.4 10.24 17.92 5.12 27.307l-85.333 147.627c-3.84 6.827-11.093 10.667-18.773 10.667-2.56 0-5.12-0.427-7.253-1.28l-106.24-42.667c-22.187 17.067-46.080 31.147-72.107 41.813l-16.213 113.067c-1.28 10.24-10.24 17.92-20.907 17.92h-170.667c-10.667 0-19.627-7.68-20.907-17.92l-16.213-113.067c-26.027-10.667-49.92-25.173-72.107-41.813l-106.24 42.667c-2.56 0.853-5.12 1.28-7.68 1.28-7.253 0-14.507-3.84-18.347-10.667l-85.333-147.627c-5.547-9.387-2.987-20.907 5.12-27.307l90.027-70.4c-1.707-13.653-2.987-27.733-2.987-41.813s1.28-28.16 2.987-41.813l-90.027-70.4c-8.107-6.4-10.24-17.92-5.12-27.307l85.333-147.627c3.84-6.827 11.093-10.667 18.773-10.667 2.56 0 5.12 0.427 7.253 1.28l106.24 42.667c22.187-17.067 46.080-31.147 72.107-41.813l16.213-113.067c1.28-10.24 10.24-17.92 20.907-17.92h170.667c10.667 0 19.627 7.68 20.907 17.92l16.213 113.067c26.027 10.667 49.92 25.173 72.107 41.813l106.24-42.667c2.56-0.853 5.12-1.28 7.68-1.28 7.253 0 14.507 3.84 18.347 10.667l85.333 147.627c5.12 9.387 2.987 20.907-5.12 27.307l-90.027 70.4zM744.533 479.147c1.707-13.227 2.133-22.187 2.133-31.147s-0.853-18.347-2.133-31.147l-5.973-48.213 37.973-29.867 46.080-35.84-29.867-51.627-54.187 21.76-44.373 17.92-38.4-29.013c-18.347-13.653-35.84-23.893-53.333-31.147l-45.227-18.347-6.827-48.213-8.533-57.6h-59.733l-8.107 57.6-6.827 48.213-45.227 18.347c-18.347 7.68-35.413 17.493-52.48 30.293l-38.827 29.867-45.227-18.347-54.187-21.76-29.867 51.627 46.080 35.84 37.973 29.867-5.973 48.213c-1.28 13.227-2.133 23.040-2.133 31.573s0.853 18.347 2.133 31.147l5.973 48.213-37.973 29.867-46.080 35.84 29.867 51.627 54.187-21.76 44.373-17.92 38.4 29.013c18.347 13.653 35.84 23.893 53.333 31.147l45.227 18.347 6.827 48.213 8.533 57.6h59.307l8.107-57.6 6.827-48.213 45.227-18.347c18.347-7.68 35.413-17.493 52.48-30.293l38.827-29.867 45.227 18.347 54.187 21.76 29.867-51.627-45.653-36.267-37.973-29.867 5.973-48.213zM512 618.667c-94.293 0-170.667-76.373-170.667-170.667s76.373-170.667 170.667-170.667 170.667 76.373 170.667 170.667-76.373 170.667-170.667 170.667zM512 362.667c-46.933 0-85.333 38.4-85.333 85.333s38.4 85.333 85.333 85.333 85.333-38.4 85.333-85.333-38.4-85.333-85.333-85.333z" />
|
||||
<glyph unicode="" glyph-name="compass" d="M512 915.2c-256 0-467.2-204.8-467.2-467.2 0-256 204.8-467.2 467.2-467.2 256 0 460.8 204.8 460.8 467.2 6.4 262.4-204.8 467.2-460.8 467.2zM646.4 320l-441.6-172.8 179.2 435.2 435.2 179.2-172.8-441.6zM588.8 454.4c0-42.415-34.385-76.8-76.8-76.8s-76.8 34.385-76.8 76.8c0 42.415 34.385 76.8 76.8 76.8s76.8-34.385 76.8-76.8z" />
|
||||
<glyph unicode="" glyph-name="connection" d="M339.2 761.6l-166.4-204.8h134.4v-441.6h64v441.6h128zM723.2 320v441.6h-64v-441.6h-134.4l166.4-204.8 160 204.8z" />
|
||||
<glyph unicode="" glyph-name="consume" d="M682.667 704v-341.333h128v-341.333h85.333v853.333c-117.76 0-213.333-95.573-213.333-170.667zM469.333 576h-85.333v298.667h-85.333v-298.667h-85.333v298.667h-85.333v-298.667c0-94.293 76.373-170.667 170.667-170.667v-384h85.333v384c94.293 0 170.667 76.373 170.667 170.667v298.667h-85.333v-298.667z" />
|
||||
<glyph unicode="" glyph-name="filter" d="M426.667 192h170.667v85.333h-170.667v-85.333zM128 704v-85.333h768v85.333h-768zM256 405.333h512v85.333h-512v-85.333z" />
|
||||
<glyph unicode="" glyph-name="folder" d="M857.6 691.2h-326.4v89.6c0 44.8-32 76.8-76.8 76.8h-249.6c-44.8 0-76.8-32-76.8-76.8v-102.4c-25.6-12.8-38.4-38.4-38.4-64v-492.8c0-44.8 32-76.8 76.8-76.8h691.2c44.8 0 76.8 32 76.8 76.8v492.8c0 44.8-32 76.8-76.8 76.8z" />
|
||||
<glyph unicode="" glyph-name="folder-open" d="M853.333 704h-341.333l-85.333 85.333h-256c-46.933 0-84.907-38.4-84.907-85.333l-0.427-512c0-46.933 38.4-85.333 85.333-85.333h682.667c46.933 0 85.333 38.4 85.333 85.333v426.667c0 46.933-38.4 85.333-85.333 85.333zM853.333 192h-682.667v426.667h682.667v-426.667z" />
|
||||
<glyph unicode="" glyph-name="grid" d="M128 838.4h320v-320h-320v320zM582.4 384h320v-320h-320v320zM128 384h320v-320h-320v320zM582.4 838.4h320v-320h-320v320z" />
|
||||
<glyph unicode="" glyph-name="leaf" d="M96 697.6c0 0 275.2 249.6 537.6 89.6 262.4-153.6 345.6-358.4 230.4-505.6-134.4 204.8-204.8 307.2-480 390.4 0 0 435.2-275.2 512-595.2-12.8-70.4-76.8-19.2-76.8-19.2l-70.4 115.2c0 0-134.4-102.4-294.4 32-268.8 236.8-57.6 499.2-358.4 492.8z" />
|
||||
<glyph unicode="" glyph-name="list" d="M108.8 806.4h806.4v-121.6h-806.4v121.6zM108.8 512h806.4v-121.6h-806.4v121.6zM108.8 217.6h806.4v-121.6h-806.4v121.6z" />
|
||||
<glyph unicode="" glyph-name="local" d="M913.152 685.248h-295.552l-98.56 98.496h-295.424v-98.496h-98.496v-590.976h689.472v98.432h98.496v492.544h0.064zM863.936 241.984h-49.344v344.768h-295.552l-98.432 98.56h-147.712v49.216h225.856l98.496-98.496h266.688v-394.048z" />
|
||||
<glyph unicode="" glyph-name="mic" d="M473.6 563.2c-12.8 12.8-38.4 12.8-51.2 0l-339.2-396.8c-6.4-6.4-12.8-12.8-12.8-25.6s6.4-19.2 12.8-25.6l96-96c6.4-6.4 12.8-12.8 25.6-12.8 6.4 0 19.2 6.4 25.6 6.4l396.8 339.2c6.4 12.8 12.8 19.2 12.8 32s-6.4 19.2-12.8 25.6l-153.6 153.6zM883.2 825.6c-44.8 44.8-102.4 70.4-166.4 70.4s-121.6-25.6-172.8-70.4c-51.2-51.2-70.4-140.8-70.4-147.2 0-12.8 0-32 19.2-44.8l198.4-198.4c6.4-6.4 25.6-19.2 44.8-19.2 0 0 0 0 0 0 6.4 0 102.4 19.2 140.8 70.4 96 89.6 96 243.2 6.4 339.2z" />
|
||||
<glyph unicode="" glyph-name="music" d="M966.4 928c-12.8 6.4-25.6 12.8-38.4 6.4l-544-128c-19.2-6.4-32-25.6-32-44.8v-422.4c-32 19.2-70.4 32-108.8 32-108.8 0-198.4-89.6-198.4-198.4s89.6-198.4 198.4-198.4c108.8 0 198.4 89.6 198.4 198.4v550.4l454.4 108.8v-364.8c-32 19.2-70.4 32-108.8 32-108.8 0-198.4-89.6-198.4-198.4s89.6-198.4 198.4-198.4 198.4 89.6 198.4 198.4v588.8c0 12.8-6.4 25.6-19.2 38.4z" />
|
||||
<glyph unicode="" glyph-name="pause" d="M256 149.333h170.667v597.333h-170.667v-597.333zM597.333 746.667v-597.333h170.667v597.333h-170.667z" />
|
||||
<glyph unicode="" glyph-name="play" d="M426.667 591.36l224.853-143.36-224.853-143.36v286.72zM341.333 746.667v-597.333l469.333 298.667-469.333 298.667z" />
|
||||
<glyph unicode="" glyph-name="play-alt" d="M367.928 187.803c3.555 0 7.168 0.222 10.747 0.665 47.168 5.889 82.615 48.877 79.137 95.89-0.003 0.081-0.007 0.158-0.010 0.238 0.084 0.483 0.131 0.98 0.131 1.487v255.812l184.632 34.369v-188.748c-9.877 2.424-20.369 3.012-30.777 1.706-47.285-5.845-82.813-48.967-79.201-96.115 3.277-43.468 38.61-76.246 82.192-76.246 3.582 0 7.225 0.228 10.824 0.678 47.211 5.885 82.736 49.004 79.19 96.098-0.007 0.081-0.013 0.161-0.020 0.242 0.067 0.416 0.097 0.843 0.097 1.279v382.986l0.077 0.967c0.252 3.038-1.219 5.946-3.757 7.641-1.917 1.283-4.277 1.682-6.493 1.199-0.040-0.007-0.081-0.017-0.121-0.024l-292.035-49.854c-4.032-0.688-6.98-4.183-6.98-8.273v-291.397c-9.904 2.448-20.393 3.048-30.767 1.749-47.305-5.835-82.81-48.961-79.147-96.125 3.327-43.458 38.697-76.229 82.279-76.226zM512-64c282.318 0 512 229.682 512 512s-229.682 512-512 512-512-229.682-512-512 229.682-512 512-512zM512 842.502c217.528 0 394.502-176.971 394.502-394.502s-176.974-394.505-394.502-394.505-394.502 176.974-394.502 394.505c0 217.528 176.974 394.502 394.502 394.502z" />
|
||||
<glyph unicode="" glyph-name="playlist" d="M704 889.6c-12.8 12.8-32 19.2-51.2 12.8-12.8-12.8-25.6-25.6-25.6-44.8v-486.4c-32 19.2-70.4 32-108.8 32-108.8 0-198.4-89.6-198.4-198.4s89.6-198.4 198.4-198.4c108.8 0 198.4 89.6 198.4 198.4v544l179.2-185.6 64 64-256 262.4zM102.4 883.2h390.4v-89.6h-390.4v89.6zM102.4 729.6h390.4v-89.6h-390.4v89.6zM102.4 576h390.4v-89.6h-390.4v89.6z" />
|
||||
<glyph unicode="" glyph-name="repeat" d="M298.667 661.333h426.667v-128l170.667 170.667-170.667 170.667v-128h-512v-256h85.333v170.667zM725.333 234.667h-426.667v128l-170.667-170.667 170.667-170.667v128h512v256h-85.333v-170.667z" />
|
||||
<glyph unicode="" glyph-name="search" d="M661.333 362.667h-33.707l-11.947 11.52c41.813 48.64 66.987 111.787 66.987 180.48 0 153.173-124.16 277.333-277.333 277.333s-277.333-124.16-277.333-277.333 124.16-277.333 277.333-277.333c68.693 0 131.84 25.173 180.48 66.987l11.52-11.947v-33.707l213.333-212.907 63.573 63.573-212.907 213.333zM405.333 362.667c-106.24 0-192 85.76-192 192s85.76 192 192 192 192-85.76 192-192-85.76-192-192-192z" />
|
||||
<glyph unicode="" glyph-name="sections" d="M129.152 823.808h274.496v-274.496h-274.496v274.496zM467.52 823.808h427.392v-54.464h-427.392v54.464zM467.52 695.808h427.392v-54.464h-427.392v54.464zM467.52 567.808h427.392v-54.464h-427.392v54.464zM129.152 370.496h274.496v-274.496h-274.496v274.496zM467.52 370.496h427.392v-54.464h-427.392v54.464zM467.52 242.496h427.392v-54.464h-427.392v54.464zM467.52 114.496h427.392v-54.464h-427.392v54.464z" />
|
||||
<glyph unicode="" glyph-name="server" d="M825.6 684.8c0 89.6-198.4 115.2-313.6 115.2s-313.6-25.6-313.6-115.2c0 0 0 0 0 0v-332.8c0 0 0 0 0 0v-166.4c0-89.6 198.4-115.2 313.6-115.2s313.6 25.6 313.6 115.2v499.2zM761.6 352c-6.4-12.8-89.6-51.2-249.6-51.2s-243.2 38.4-249.6 51.2v89.6c64-25.6 172.8-38.4 249.6-38.4s185.6 12.8 249.6 38.4v-89.6zM512 736c160 0 243.2-38.4 249.6-51.2-6.4-12.8-89.6-51.2-249.6-51.2s-243.2 38.4-249.6 44.8v0c6.4 19.2 89.6 57.6 249.6 57.6zM262.4 608c64-25.6 172.8-38.4 249.6-38.4s185.6 12.8 249.6 38.4v-89.6c-6.4-12.8-89.6-51.2-249.6-51.2s-243.2 38.4-249.6 51.2v89.6zM512 134.4c-160 0-243.2 38.4-249.6 51.2v96c70.4-32 179.2-38.4 249.6-38.4 76.8 0 185.6 12.8 249.6 38.4v-89.6c-6.4-19.2-89.6-57.6-249.6-57.6z" />
|
||||
<glyph unicode="" glyph-name="shuffle" d="M451.84 568.747l-221.013 220.587-60.16-60.16 220.587-220.587 60.587 60.16zM618.667 789.333l87.040-87.040-535.040-535.467 60.16-60.16 535.467 535.040 87.040-87.040v234.667h-234.667zM632.747 387.84l-60.16-60.16 133.547-133.547-87.467-87.467h234.667v234.667l-87.040-87.040-133.547 133.547z" />
|
||||
<glyph unicode="" glyph-name="skip" d="M256 192l362.667 256-362.667 256v-512zM341.333 539.307l129.28-91.307-129.28-91.307v182.613zM682.667 704h85.333v-512h-85.333v512z" />
|
||||
<glyph unicode="" glyph-name="soundcloud" d="M1.728 259.52c0-12.608 4.608-22.208 13.76-28.608 9.28-6.656 19.072-8.896 29.568-6.912 9.792 1.792 16.704 5.376 20.672 10.496 4.032 5.056 5.952 13.504 5.952 25.216v137.792c0 9.856-3.392 18.112-10.176 25.024-6.848 6.848-15.168 10.24-25.024 10.24-9.408 0-17.6-3.392-24.448-10.24-6.848-6.912-10.304-15.168-10.304-25.024v-137.984zM111.104 200.64c0-9.28 3.392-16.128 9.856-20.608 6.464-4.544 14.72-6.912 24.896-6.912 10.56 0 19.008 2.368 25.408 6.912 6.592 4.48 9.792 11.456 9.792 20.608v321.472c0 9.472-3.52 17.664-10.176 24.512-6.848 6.848-15.104 10.304-25.024 10.304-9.472 0-17.6-3.456-24.512-10.304-6.72-6.784-10.24-14.976-10.24-24.512v-321.472zM220.032 185.344c0-9.28 3.456-16.128 9.984-20.736 6.72-4.544 15.232-6.848 25.728-6.848 10.048 0 18.432 2.304 25.024 6.848 6.464 4.608 9.664 11.584 9.664 20.736v293.504c0 9.792-3.456 18.24-10.24 25.216-6.848 6.912-14.912 10.496-24.384 10.496-9.856 0-18.24-3.584-25.28-10.496-6.912-6.912-10.496-15.36-10.496-25.216v-293.504zM329.472 184c0-17.472 11.84-26.24 35.264-26.24 23.488 0 35.2 8.768 35.2 26.24v475.584c0 26.752-8.192 41.792-24.32 45.248-10.368 2.496-20.736-0.448-30.848-9.088-10.176-8.512-15.296-20.544-15.296-36.16v-475.584zM440.832 170.112v517.504c0 16.576 4.928 26.368 14.72 29.504 21.312 5.12 42.432 7.68 63.296 7.68 48.512 0 93.632-11.456 135.552-34.24 41.856-22.848 75.84-54.080 101.632-93.568 25.664-39.36 40.832-82.88 44.864-130.496 19.392 8.256 40 12.352 62.016 12.352 44.16 0 82.24-15.744 113.728-47.040 31.616-31.424 47.36-69.184 47.36-113.152 0-44.352-15.744-82.368-47.296-113.664-31.552-31.36-69.44-47.104-113.344-47.104l-413.952 0.576c-2.752 1.024-4.928 2.624-6.528 5.248-1.408 2.304-2.048 4.544-2.048 6.4v0z" />
|
||||
<glyph unicode="" glyph-name="speaker" d="M725.333 874.667h-426.667c-46.933 0-85.333-38.4-85.333-85.333v-682.667c0-46.933 38.4-84.907 85.333-84.907l426.667-0.427c46.933 0 85.333 38.4 85.333 85.333v682.667c0 46.933-38.4 85.333-85.333 85.333zM298.667 106.667v682.667h426.667v-682.667h-426.667zM512 576c46.933 0 85.333 38.4 85.333 85.333s-38.4 85.333-85.333 85.333c-47.36 0-85.333-38.4-85.333-85.333s37.973-85.333 85.333-85.333zM512 490.667c-94.293 0-170.667-76.373-170.667-170.667s76.373-170.667 170.667-170.667 170.667 76.373 170.667 170.667-76.373 170.667-170.667 170.667zM512 234.667c-46.933 0-85.333 38.4-85.333 85.333s38.4 85.333 85.333 85.333 85.333-38.4 85.333-85.333-38.4-85.333-85.333-85.333z" />
|
||||
<glyph unicode="" glyph-name="speaker-group" d="M776.533 917.333h-358.4c-42.24 0-76.8-34.56-76.8-76.8v-614.4c0-42.24 34.56-76.373 76.8-76.373l358.4-0.427c42.24 0 76.8 34.56 76.8 76.8v614.4c0 42.24-34.56 76.8-76.8 76.8zM768 234.667l-341.333 0.427v596.907h341.333v-597.333zM597.333 618.667c46.933 0 85.333 37.973 85.333 85.333s-38.4 85.333-85.333 85.333-85.333-37.973-85.333-85.333 38.4-85.333 85.333-85.333zM597.333 277.333c82.347 0 149.333 66.987 149.333 149.333s-66.987 149.333-149.333 149.333c-82.347 0-149.333-66.987-149.333-149.333s66.987-149.333 149.333-149.333zM597.333 490.667c35.413 0 64-28.587 64-64s-28.587-64-64-64-64 28.587-64 64 28.587 64 64 64zM256 746.667h-85.333v-682.667c0-46.933 37.973-85.333 85.333-85.333h426.667v85.333h-426.667v682.667z" />
|
||||
<glyph unicode="" glyph-name="spotify" d="M508.16 839.232c-216.896 0-394.24-177.408-394.24-394.368 0-217.024 177.344-394.304 394.24-394.304 216.832 0 394.24 177.344 394.24 394.304s-175.552 394.368-394.24 394.368zM689.472 269.504c-7.872-11.904-21.76-15.744-33.408-7.872-92.736 57.152-209.088 68.992-347.008 37.376-13.76-3.904-25.536 6.016-29.504 17.856-3.968 13.76 5.76 25.536 17.728 29.504 149.76 33.472 280 19.776 382.4-43.392 13.824-5.952 15.744-21.696 9.792-33.472zM736.896 377.984c-9.856-14.016-27.712-19.776-41.344-9.984-106.496 65.152-268.16 84.928-392.32 45.376-15.872-4.032-33.6 3.904-37.568 19.776-3.968 15.744 3.968 33.536 19.648 37.376 144 43.392 321.344 21.76 443.712-53.248 11.712-5.888 17.664-25.472 7.872-39.296zM740.736 488.256c-126.080 75.072-337.024 82.944-457.216 45.44-19.776-5.952-39.552 5.888-45.44 23.616-5.888 19.776 5.888 39.424 23.616 45.376 139.968 41.344 370.624 33.472 516.544-53.248 17.728-9.856 23.616-33.472 13.76-51.264-9.728-13.76-33.472-19.648-51.264-9.92z" />
|
||||
<glyph unicode="" glyph-name="star" d="M512 908.8c-12.8 0-19.2-6.4-25.6-25.6l-128-256-281.6-38.4c-25.6-6.4-32-12.8-32-25.6 0-6.4 6.4-19.2 12.8-25.6l204.8-198.4-51.2-281.6c0-6.4 0-6.4 0-12.8s0-12.8 6.4-19.2 12.8-6.4 19.2-6.4 12.8 0 25.6 6.4l256 134.4 256-134.4c6.4-6.4 12.8-6.4 25.6-6.4 6.4 0 12.8 0 19.2 6.4s6.4 12.8 6.4 19.2 0 6.4 0 12.8l-51.2 281.6 204.8 198.4c12.8 12.8 12.8 19.2 12.8 25.6 0 12.8-12.8 25.6-32 25.6l-281.6 38.4-128 256c-19.2 19.2-25.6 25.6-38.4 25.6v0z" />
|
||||
<glyph unicode="" glyph-name="stop" d="M682.667 618.667v-341.333h-341.333v341.333h341.333zM768 704h-512v-512h512v512z" />
|
||||
</font></defs></svg>
|
||||
|
After Width: | Height: | Size: 17 KiB |
BIN
mopidy_iris/static/assets/fonts/iris.ttf
Normal file
BIN
mopidy_iris/static/assets/fonts/iris.woff
Normal file
BIN
mopidy_iris/static/assets/fonts/overpass-black-webfont.woff
Normal file
BIN
mopidy_iris/static/assets/fonts/overpass-black-webfont.woff2
Normal file
BIN
mopidy_iris/static/assets/fonts/overpass-bold-webfont.woff
Normal file
BIN
mopidy_iris/static/assets/fonts/overpass-bold-webfont.woff2
Normal file
BIN
mopidy_iris/static/assets/fonts/overpass-extrabold-webfont.woff
Normal file
BIN
mopidy_iris/static/assets/fonts/overpass-extrabold-webfont.woff2
Normal file
BIN
mopidy_iris/static/assets/fonts/overpass-italic-webfont.woff
Normal file
BIN
mopidy_iris/static/assets/fonts/overpass-italic-webfont.woff2
Normal file
BIN
mopidy_iris/static/assets/fonts/overpass-regular-webfont.woff
Normal file
BIN
mopidy_iris/static/assets/fonts/overpass-regular-webfont.woff2
Normal file
BIN
mopidy_iris/static/assets/icon-no-bg-512.png
Normal file
|
After Width: | Height: | Size: 4.7 KiB |
13
mopidy_iris/static/assets/icons/genius.svg
Normal file
@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 22.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 192 192" style="enable-background:new 0 0 192 192;" xml:space="preserve">
|
||||
<path fill="#121212" d="M54.8,38.5c-10,33.6-5.1,64.3,20,89.4s55.9,29.7,89.5,20.2c-17.7,17.6-39.2,24.3-63.4,21.6
|
||||
c-35-4.1-59.6-30.3-66.6-59.5C27.2,80.8,39.6,50.9,54.8,38.5z"/>
|
||||
<path fill="#121212" d="M91,43.9c2.3-4.1,5.5-7.6,9.1-10.7c17.3-14.7,43.6-14.7,61-0.1c2.9,2.4,4.5,5,4.1,9c-0.4,4.6-0.1,9.3-0.1,14.5
|
||||
c-6.3,0-12.3,0.1-18.2-0.1c-0.8,0-1.6-0.8-2.3-1.3c-14.9-12.7-31.7-16.5-50.5-10.9c-0.8,0.2-1.7,0.3-2.5,0.5
|
||||
C91.5,44.6,91.2,44.2,91,43.9z"/>
|
||||
<path fill="#121212" d="M143,118.2c-0.1-2.4-0.2-4.6-0.3-7.3c-1.3-0.1-2.6-0.2-3.8-0.3c-3.9-0.1-7.8,0.2-11.7-0.1
|
||||
c-9.3-0.5-16.9-8.2-17-17.1c-0.2-9.6,6.9-17.1,17-17.9c0.2,0.8,0.4,1.6,0.5,2.5c2,9.3,9,15,18.6,15.1c4.8,0.1,9.6,0,14.4,0
|
||||
c1.2,0,2.6,0.1,4.4,0.2c0,4.7,0.1,9.2-0.1,13.7c0,0.8-0.7,1.6-1.2,2.3C159.7,113.3,149.8,117.6,143,118.2z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
19
mopidy_iris/static/assets/icons/jellyfin.svg
Normal file
@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- ***** BEGIN LICENSE BLOCK *****
|
||||
- Part of the Jellyfin project (https://jellyfin.media)
|
||||
-
|
||||
- All copyright belongs to the Jellyfin contributors; a full list can
|
||||
- be found in the file CONTRIBUTORS.md
|
||||
-
|
||||
- This work is licensed under the Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
- To view a copy of this license, visit http://creativecommons.org/licenses/by-sa/4.0/.
|
||||
- ***** END LICENSE BLOCK ***** -->
|
||||
<svg id="icon-transparent-white"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 512 512">
|
||||
<title>icon-transparent-white</title>
|
||||
<g id="icon-transparent">
|
||||
<path id="inner-shape" d="M256,201.62c-20.44,0-86.23,119.29-76.2,139.43s142.48,19.92,152.4,0S276.47,201.63,256,201.62Z" fill="#ffffff"/>
|
||||
<path id="outer-shape" d="M256,23.3C194.44,23.3-3.82,382.73,26.41,443.43s429.34,60,459.24,0S317.62,23.3,256,23.3ZM406.51,390.76c-19.59,39.33-281.08,39.77-300.89,0S215.71,115.48,256.06,115.48,426.1,351.42,406.51,390.76Z" fill="#ffffff"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
11
mopidy_iris/static/assets/icons/tidal.svg
Normal file
@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1"
|
||||
id="svg477" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" sodipodi:docname="tidal.svg" inkscape:version="0.92.0 r15299"
|
||||
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="46.459px"
|
||||
height="30.975px" viewBox="0 0 46.459 30.975" enable-background="new 0 0 46.459 30.975" xml:space="preserve">
|
||||
<path fill="#121212" d="M15.486,23.23l7.744-7.744l7.742,7.744l-7.742,7.745L15.486,23.23z M7.743-0.001L0,7.742l7.742,7.745
|
||||
l7.744-7.744L7.743-0.001z M38.715,15.488l7.744-7.744L38.715,0l-7.742,7.743V7.741L23.23,0.002l-7.744,7.739l7.744,7.744
|
||||
l7.741-7.742L38.715,15.488z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
BIN
mopidy_iris/static/assets/logo.png
Normal file
|
After Width: | Height: | Size: 6.5 KiB |
22
mopidy_iris/static/assets/logo.svg
Normal file
@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 21.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 141.7 141.7" style="enable-background:new 0 0 141.7 141.7;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#FFFFFF;}
|
||||
</style>
|
||||
<g>
|
||||
<path class="st0" d="M3.9,102.9V40h10.8v62.9H3.9z"/>
|
||||
<path class="st0" d="M20.6,102.9V57h10.5v4.8c1.8-3.8,5-5.9,9.4-5.9c3.2,0,6.1,1,8.5,3.1l-1.5,9.6c-2.3-1.6-4.9-2.4-7.8-2.4
|
||||
c-2.4,0-4.4,0.8-6.1,2.5c-1.7,1.7-2.5,4.4-2.5,8.5v25.7H20.6z"/>
|
||||
<path class="st0" d="M62.9,48.8c-1.2,1.2-2.6,1.8-4.4,1.8c-1.7,0-3.2-0.6-4.4-1.8c-1.2-1.2-1.8-2.7-1.8-4.4s0.6-3.2,1.8-4.4
|
||||
c1.2-1.2,2.7-1.8,4.4-1.8s3.2,0.6,4.4,1.8c1.2,1.2,1.8,2.6,1.8,4.4S64.1,47.6,62.9,48.8z M53.2,102.9V57h10.5v45.9H53.2z"/>
|
||||
<path class="st0" d="M84.9,103.9c-3.7,0-7.2-0.7-10.5-2.1c-3.2-1.4-5.8-3.3-7.4-5.8l7.2-6.1c3.2,3.2,6.8,4.9,10.7,4.9
|
||||
c5,0,7.5-1.5,7.5-4.4c0-1-0.4-1.9-1.3-2.8c-0.9-0.8-1.8-1.5-2.8-1.9c-1-0.4-2.6-1.1-4.9-2c-5.3-1.7-9.1-3.7-11.5-6
|
||||
s-3.6-5.3-3.6-8.9c0-4,1.5-7.2,4.7-9.4c3-2.2,7-3.3,11.7-3.3c7,0,12.4,2.3,16.5,7.1l-7.3,6c-2.7-2.5-5.8-3.8-9.2-3.8
|
||||
c-4.1-0.1-6.2,1.1-6.2,3.6c0,1.2,0.8,2.3,2.3,3.2c1.5,0.9,3.7,1.8,6.7,2.8c5,1.7,8.7,3.6,11.3,6c2.5,2.3,3.8,5.5,3.8,9.5
|
||||
c0,4.3-1.6,7.8-4.8,10.1C94.5,102.8,90.2,103.9,84.9,103.9z"/>
|
||||
</g>
|
||||
<polygon class="st0" points="121,74.6 110.6,64.5 110.6,97 121,87 "/>
|
||||
<polygon class="st0" points="121,64.5 121,69.4 132.8,80.7 121,92.2 121,97 137.9,80.7 "/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.6 KiB |