mirror of
https://github.com/austinried/subtracks.git
synced 2025-12-27 00:59:28 +01:00
reorg again, absolute (module) imports
This commit is contained in:
parent
a94a011a18
commit
ea4421b7af
@ -1,11 +1,11 @@
|
||||
import React from 'react'
|
||||
import { DarkTheme, NavigationContainer } from '@react-navigation/native'
|
||||
import SplashPage from './src/components/SplashPage'
|
||||
import RootNavigator from './src/components/navigation/RootNavigator'
|
||||
import SplashPage from '@app/screens/SplashPage'
|
||||
import RootNavigator from '@app/navigation/RootNavigator'
|
||||
import { Provider } from 'jotai'
|
||||
import { StatusBar, View } from 'react-native'
|
||||
import colors from './src/styles/colors'
|
||||
import TrackPlayerState from './src/components/TrackPlayerState'
|
||||
import colors from '@app/styles/colors'
|
||||
import TrackPlayerState from '@app/components/TrackPlayerState'
|
||||
|
||||
const theme = { ...DarkTheme }
|
||||
theme.colors.background = colors.gradient.high
|
||||
@ -3,9 +3,9 @@ import React from 'react'
|
||||
import { ActivityIndicator, View } from 'react-native'
|
||||
import FastImage from 'react-native-fast-image'
|
||||
import LinearGradient from 'react-native-linear-gradient'
|
||||
import { albumArtAtomFamily } from '../../state/music'
|
||||
import colors from '../../styles/colors'
|
||||
import CoverArt from './CoverArt'
|
||||
import { albumArtAtomFamily } from '@app/state/music'
|
||||
import colors from '@app/styles/colors'
|
||||
import CoverArt from '@app/components/CoverArt'
|
||||
|
||||
interface AlbumArtProps {
|
||||
id: string
|
||||
@ -19,7 +19,7 @@ const AlbumArt: React.FC<AlbumArtProps> = ({ id, height, width }) => {
|
||||
const Placeholder = () => (
|
||||
<LinearGradient colors={[colors.accent, colors.accentLow]}>
|
||||
<FastImage
|
||||
source={require('../../../res/record.png')}
|
||||
source={require('../../res/record.png')}
|
||||
style={{ height, width }}
|
||||
resizeMode={FastImage.resizeMode.contain}
|
||||
/>
|
||||
@ -3,9 +3,9 @@ import React from 'react'
|
||||
import { ActivityIndicator, View } from 'react-native'
|
||||
import FastImage from 'react-native-fast-image'
|
||||
import LinearGradient from 'react-native-linear-gradient'
|
||||
import { artistArtAtomFamily } from '../../state/music'
|
||||
import colors from '../../styles/colors'
|
||||
import CoverArt from './CoverArt'
|
||||
import { artistArtAtomFamily } from '@app/state/music'
|
||||
import colors from '@app/styles/colors'
|
||||
import CoverArt from '@app/components/CoverArt'
|
||||
|
||||
interface ArtistArtSizeProps {
|
||||
height: number
|
||||
@ -131,7 +131,7 @@ const NoneUp: React.FC<ArtistArtSizeProps> = ({ height, width }) => {
|
||||
return (
|
||||
<PlaceholderContainer height={height} width={width}>
|
||||
<FastImage
|
||||
source={require('../../../res/mic_on-fill.png')}
|
||||
source={require('../../res/mic_on-fill.png')}
|
||||
style={{
|
||||
height: height - height / 4,
|
||||
width: width - width / 4,
|
||||
@ -1,7 +1,7 @@
|
||||
import React, { useState } from 'react'
|
||||
import { GestureResponderEvent, Pressable, Text } from 'react-native'
|
||||
import colors from '../../styles/colors'
|
||||
import text from '../../styles/text'
|
||||
import colors from '@app/styles/colors'
|
||||
import text from '@app/styles/text'
|
||||
|
||||
const Button: React.FC<{
|
||||
title: string
|
||||
@ -1,7 +1,7 @@
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import { ActivityIndicator, StyleSheet, View } from 'react-native'
|
||||
import FastImage from 'react-native-fast-image'
|
||||
import colors from '../../styles/colors'
|
||||
import colors from '@app/styles/colors'
|
||||
|
||||
const CoverArt: React.FC<{
|
||||
PlaceholderComponent: () => JSX.Element
|
||||
@ -1,7 +1,7 @@
|
||||
import React from 'react'
|
||||
import { useWindowDimensions, ViewStyle } from 'react-native'
|
||||
import LinearGradient from 'react-native-linear-gradient'
|
||||
import colorStyles from '../../styles/colors'
|
||||
import colorStyles from '@app/styles/colors'
|
||||
|
||||
const GradientBackground: React.FC<{
|
||||
height?: number | string
|
||||
@ -1,7 +1,7 @@
|
||||
import React from 'react'
|
||||
import { FlatList, FlatListProps, useWindowDimensions } from 'react-native'
|
||||
import colors from '../../styles/colors'
|
||||
import GradientBackground from './GradientBackground'
|
||||
import colors from '@app/styles/colors'
|
||||
import GradientBackground from '@app/components/GradientBackground'
|
||||
|
||||
function GradientFlatList<ItemT>(props: FlatListProps<ItemT>) {
|
||||
const layout = useWindowDimensions()
|
||||
@ -1,7 +1,7 @@
|
||||
import React from 'react'
|
||||
import { ScrollView, ScrollViewProps, ViewStyle } from 'react-native'
|
||||
import colors from '../../styles/colors'
|
||||
import GradientBackground from './GradientBackground'
|
||||
import colors from '@app/styles/colors'
|
||||
import GradientBackground from '@app/components/GradientBackground'
|
||||
|
||||
const GradientScrollView: React.FC<ScrollViewProps> = props => {
|
||||
props.style = props.style || {}
|
||||
@ -4,8 +4,8 @@ import { ViewStyle } from 'react-native'
|
||||
import FastImage from 'react-native-fast-image'
|
||||
import ImageColors from 'react-native-image-colors'
|
||||
import { AndroidImageColors } from 'react-native-image-colors/lib/typescript/types'
|
||||
import colors from '../../styles/colors'
|
||||
import GradientBackground from './GradientBackground'
|
||||
import colors from '@app/styles/colors'
|
||||
import GradientBackground from '@app/components/GradientBackground'
|
||||
|
||||
const ImageGradientBackground: React.FC<{
|
||||
height?: number | string
|
||||
@ -1,7 +1,7 @@
|
||||
import React, { useState } from 'react'
|
||||
import { LayoutRectangle, ScrollView, ScrollViewProps } from 'react-native'
|
||||
import colors from '../../styles/colors'
|
||||
import ImageGradientBackground from './ImageGradientBackground'
|
||||
import colors from '@app/styles/colors'
|
||||
import ImageGradientBackground from '@app/components/ImageGradientBackground'
|
||||
|
||||
const ImageGradientScrollView: React.FC<ScrollViewProps & { imageUri?: string; imageKey?: string }> = props => {
|
||||
const [layout, setLayout] = useState<LayoutRectangle | undefined>(undefined)
|
||||
@ -2,12 +2,12 @@ import React from 'react'
|
||||
import { Pressable, StyleSheet, Text, View } from 'react-native'
|
||||
import { useNavigation } from '@react-navigation/native'
|
||||
import { useAtomValue } from 'jotai/utils'
|
||||
import { currentTrackAtom, playerStateAtom, usePause, usePlay, useProgress } from '../state/trackplayer'
|
||||
import CoverArt from './common/CoverArt'
|
||||
import colors from '../styles/colors'
|
||||
import { Font } from '../styles/text'
|
||||
import { currentTrackAtom, playerStateAtom, usePause, usePlay, useProgress } from '@app/state/trackplayer'
|
||||
import CoverArt from '@app/components/CoverArt'
|
||||
import colors from '@app/styles/colors'
|
||||
import { Font } from '@app/styles/text'
|
||||
import { State } from 'react-native-track-player'
|
||||
import PressableOpacity from './common/PressableOpacity'
|
||||
import PressableOpacity from '@app/components/PressableOpacity'
|
||||
import IconFA5 from 'react-native-vector-icons/FontAwesome5'
|
||||
|
||||
const ProgressBar = () => {
|
||||
@ -41,4 +41,4 @@ const PressableOpacity: React.FC<PressableOpacityProps> = props => {
|
||||
)
|
||||
}
|
||||
|
||||
export default PressableOpacity
|
||||
export default React.memo(PressableOpacity)
|
||||
@ -13,7 +13,7 @@ import {
|
||||
useRefreshPlayerState,
|
||||
useRefreshProgress,
|
||||
useRefreshQueue,
|
||||
} from '../state/trackplayer'
|
||||
} from '@app/state/trackplayer'
|
||||
|
||||
const AppActiveResponder: React.FC<{
|
||||
update: () => void
|
||||
@ -1,27 +1,27 @@
|
||||
import React, { useState } from 'react'
|
||||
import { Text, View, Pressable } from 'react-native'
|
||||
import { BottomTabBarProps } from '@react-navigation/bottom-tabs'
|
||||
import textStyles from '../../styles/text'
|
||||
import colors from '../../styles/colors'
|
||||
import textStyles from '@app/styles/text'
|
||||
import colors from '@app/styles/colors'
|
||||
import FastImage from 'react-native-fast-image'
|
||||
import NowPlayingBar from '../NowPlayingBar'
|
||||
import NowPlayingBar from '@app/components/NowPlayingBar'
|
||||
|
||||
const icons: { [key: string]: any } = {
|
||||
home: {
|
||||
regular: require('../../../res/home.png'),
|
||||
fill: require('../../../res/home-fill.png'),
|
||||
regular: require('../../res/home.png'),
|
||||
fill: require('../../res/home-fill.png'),
|
||||
},
|
||||
library: {
|
||||
regular: require('../../../res/library.png'),
|
||||
fill: require('../../../res/library-fill.png'),
|
||||
regular: require('../../res/library.png'),
|
||||
fill: require('../../res/library-fill.png'),
|
||||
},
|
||||
search: {
|
||||
regular: require('../../../res/search.png'),
|
||||
fill: require('../../../res/search-fill.png'),
|
||||
regular: require('../../res/search.png'),
|
||||
fill: require('../../res/search-fill.png'),
|
||||
},
|
||||
settings: {
|
||||
regular: require('../../../res/settings.png'),
|
||||
fill: require('../../../res/settings-fill.png'),
|
||||
regular: require('../../res/settings.png'),
|
||||
fill: require('../../res/settings-fill.png'),
|
||||
},
|
||||
}
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
import React from 'react'
|
||||
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs'
|
||||
import SettingsView from '../Settings'
|
||||
import NowPlayingLayout from '../NowPlayingLayout'
|
||||
import ArtistsList from '../ArtistsList'
|
||||
import LibraryTopTabNavigator from './LibraryTopTabNavigator'
|
||||
import BottomTabBar from '../common/BottomTabBar'
|
||||
import SettingsView from '@app/screens/Settings'
|
||||
import NowPlayingLayout from '@app/screens/NowPlayingLayout'
|
||||
import ArtistsList from '@app/screens/ArtistsList'
|
||||
import LibraryTopTabNavigator from '@app/navigation/LibraryTopTabNavigator'
|
||||
import BottomTabBar from '@app/navigation/BottomTabBar'
|
||||
|
||||
const Tab = createBottomTabNavigator()
|
||||
|
||||
@ -1,15 +1,15 @@
|
||||
import React from 'react'
|
||||
import { StatusBar, View } from 'react-native'
|
||||
import { createMaterialTopTabNavigator } from '@react-navigation/material-top-tabs'
|
||||
import AlbumsTab from '../library/AlbumsTab'
|
||||
import ArtistsTab from '../library/ArtistsTab'
|
||||
import PlaylistsTab from '../library/PlaylistsTab'
|
||||
import AlbumsTab from '@app/screens/LibraryAlbums'
|
||||
import ArtistsTab from '@app/screens/LibraryArtists'
|
||||
import PlaylistsTab from '@app/screens/LibraryPlaylists'
|
||||
import { createNativeStackNavigator, NativeStackNavigationProp } from 'react-native-screens/native-stack'
|
||||
import AlbumView from '../common/AlbumView'
|
||||
import AlbumView from '@app/screens/AlbumView'
|
||||
import { RouteProp } from '@react-navigation/native'
|
||||
import text from '../../styles/text'
|
||||
import colors from '../../styles/colors'
|
||||
import ArtistView from '../common/ArtistView'
|
||||
import text from '@app/styles/text'
|
||||
import colors from '@app/styles/colors'
|
||||
import ArtistView from '@app/screens/ArtistView'
|
||||
|
||||
const Tab = createMaterialTopTabNavigator()
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import React from 'react'
|
||||
import { createNativeStackNavigator } from 'react-native-screens/native-stack'
|
||||
import NowPlayingLayout from '../NowPlayingLayout'
|
||||
import BottomTabNavigator from './BottomTabNavigator'
|
||||
import NowPlayingLayout from '@app/screens/NowPlayingLayout'
|
||||
import BottomTabNavigator from '@app/navigation/BottomTabNavigator'
|
||||
|
||||
const RootStack = createNativeStackNavigator()
|
||||
|
||||
@ -4,15 +4,15 @@ import React, { useEffect } from 'react'
|
||||
import { ActivityIndicator, GestureResponderEvent, StyleSheet, Text, useWindowDimensions, View } from 'react-native'
|
||||
import IconFA from 'react-native-vector-icons/FontAwesome'
|
||||
import IconMat from 'react-native-vector-icons/MaterialIcons'
|
||||
import { albumAtomFamily } from '../../state/music'
|
||||
import { currentTrackAtom, useSetQueue } from '../../state/trackplayer'
|
||||
import colors from '../../styles/colors'
|
||||
import text, { Font } from '../../styles/text'
|
||||
import AlbumArt from './AlbumArt'
|
||||
import Button from './Button'
|
||||
import GradientBackground from './GradientBackground'
|
||||
import ImageGradientScrollView from './ImageGradientScrollView'
|
||||
import PressableOpacity from './PressableOpacity'
|
||||
import { albumAtomFamily } from '@app/state/music'
|
||||
import { currentTrackAtom, useSetQueue } from '@app/state/trackplayer'
|
||||
import colors from '@app/styles/colors'
|
||||
import text, { Font } from '@app/styles/text'
|
||||
import AlbumArt from '@app/components/AlbumArt'
|
||||
import Button from '@app/components/Button'
|
||||
import GradientBackground from '@app/components/GradientBackground'
|
||||
import ImageGradientScrollView from '@app/components/ImageGradientScrollView'
|
||||
import PressableOpacity from '@app/components/PressableOpacity'
|
||||
|
||||
const SongItem: React.FC<{
|
||||
id: string
|
||||
@ -2,10 +2,10 @@ import { useNavigation } from '@react-navigation/native'
|
||||
import { useAtomValue } from 'jotai/utils'
|
||||
import React, { useEffect } from 'react'
|
||||
import { Text } from 'react-native'
|
||||
import { artistInfoAtomFamily } from '../../state/music'
|
||||
import text from '../../styles/text'
|
||||
import ArtistArt from './ArtistArt'
|
||||
import GradientScrollView from './GradientScrollView'
|
||||
import { artistInfoAtomFamily } from '@app/state/music'
|
||||
import text from '@app/styles/text'
|
||||
import ArtistArt from '@app/components/ArtistArt'
|
||||
import GradientScrollView from '@app/components/GradientScrollView'
|
||||
|
||||
const ArtistDetails: React.FC<{ id: string }> = ({ id }) => {
|
||||
const artist = useAtomValue(artistInfoAtomFamily(id))
|
||||
@ -1,8 +1,8 @@
|
||||
import React from 'react'
|
||||
import { FlatList, Text, View } from 'react-native'
|
||||
import { useAtomValue } from 'jotai/utils'
|
||||
import { Artist } from '../models/music'
|
||||
import { artistsAtom } from '../state/music'
|
||||
import { Artist } from '@app/models/music'
|
||||
import { artistsAtom } from '@app/state/music'
|
||||
|
||||
const ArtistItem: React.FC<{ item: Artist }> = ({ item }) => (
|
||||
<View>
|
||||
@ -2,11 +2,11 @@ import { useNavigation } from '@react-navigation/native'
|
||||
import { useAtomValue } from 'jotai/utils'
|
||||
import React, { useEffect } from 'react'
|
||||
import { Pressable, Text, View } from 'react-native'
|
||||
import { Album } from '../../models/music'
|
||||
import { albumsAtom, albumsUpdatingAtom, useUpdateAlbums } from '../../state/music'
|
||||
import textStyles from '../../styles/text'
|
||||
import AlbumArt from '../common/AlbumArt'
|
||||
import GradientFlatList from '../common/GradientFlatList'
|
||||
import { Album } from '@app/models/music'
|
||||
import { albumsAtom, albumsUpdatingAtom, useUpdateAlbums } from '@app/state/music'
|
||||
import textStyles from '@app/styles/text'
|
||||
import AlbumArt from '@app/components/AlbumArt'
|
||||
import GradientFlatList from '@app/components/GradientFlatList'
|
||||
|
||||
const AlbumItem: React.FC<{
|
||||
id: string
|
||||
@ -3,11 +3,11 @@ import { useAtomValue } from 'jotai/utils'
|
||||
import React, { useEffect } from 'react'
|
||||
import { Pressable } from 'react-native'
|
||||
import { Text } from 'react-native'
|
||||
import { Artist } from '../../models/music'
|
||||
import { artistsAtom, artistsUpdatingAtom, useUpdateArtists } from '../../state/music'
|
||||
import textStyles from '../../styles/text'
|
||||
import ArtistArt from '../common/ArtistArt'
|
||||
import GradientFlatList from '../common/GradientFlatList'
|
||||
import { Artist } from '@app/models/music'
|
||||
import { artistsAtom, artistsUpdatingAtom, useUpdateArtists } from '@app/state/music'
|
||||
import textStyles from '@app/styles/text'
|
||||
import ArtistArt from '@app/components/ArtistArt'
|
||||
import GradientFlatList from '@app/components/GradientFlatList'
|
||||
|
||||
const ArtistItem: React.FC<{ item: Artist }> = ({ item }) => {
|
||||
const navigation = useNavigation()
|
||||
@ -1,5 +1,5 @@
|
||||
import React from 'react'
|
||||
import GradientBackground from '../common/GradientBackground'
|
||||
import GradientBackground from '@app/components/GradientBackground'
|
||||
|
||||
const PlaylistsTab = () => <GradientBackground />
|
||||
|
||||
@ -18,13 +18,13 @@ import {
|
||||
usePlay,
|
||||
usePrevious,
|
||||
useProgress,
|
||||
} from '../state/trackplayer'
|
||||
import colors from '../styles/colors'
|
||||
import { Font } from '../styles/text'
|
||||
import { formatDuration } from '../util'
|
||||
import CoverArt from './common/CoverArt'
|
||||
import ImageGradientBackground from './common/ImageGradientBackground'
|
||||
import PressableOpacity from './common/PressableOpacity'
|
||||
} from '@app/state/trackplayer'
|
||||
import colors from '@app/styles/colors'
|
||||
import { Font } from '@app/styles/text'
|
||||
import formatDuration from '@app/util/formatDuration'
|
||||
import CoverArt from '@app/components/CoverArt'
|
||||
import ImageGradientBackground from '@app/components/ImageGradientBackground'
|
||||
import PressableOpacity from '@app/components/PressableOpacity'
|
||||
|
||||
const NowPlayingHeader = () => {
|
||||
const queueName = useAtomValue(queueNameAtom)
|
||||
@ -4,9 +4,9 @@ import md5 from 'md5'
|
||||
import React from 'react'
|
||||
import { Button, Text, View } from 'react-native'
|
||||
import { v4 as uuidv4 } from 'uuid'
|
||||
import { appSettingsAtom } from '../state/settings'
|
||||
import { getAllKeys, multiRemove } from '../storage/asyncstorage'
|
||||
import text from '../styles/text'
|
||||
import { appSettingsAtom } from '@app/state/settings'
|
||||
import { getAllKeys, multiRemove } from '@app/storage/asyncstorage'
|
||||
import text from '@app/styles/text'
|
||||
|
||||
const TestControls = () => {
|
||||
const navigation = useNavigation()
|
||||
@ -1,7 +1,7 @@
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import { Text, View } from 'react-native'
|
||||
import RNFS from 'react-native-fs'
|
||||
import paths from '../paths'
|
||||
import paths from '@app/util/paths'
|
||||
|
||||
async function mkdir(path: string): Promise<void> {
|
||||
const exists = await RNFS.exists(path)
|
||||
@ -1,5 +1,5 @@
|
||||
import TrackPlayer, { Event } from 'react-native-track-player'
|
||||
import { trackPlayerCommands } from '../state/trackplayer'
|
||||
import { trackPlayerCommands } from '@app/state/trackplayer'
|
||||
|
||||
module.exports = async function () {
|
||||
TrackPlayer.addEventListener(Event.RemotePlay, () => trackPlayerCommands.enqueue(TrackPlayer.play))
|
||||
@ -1,10 +1,10 @@
|
||||
import { atom, useAtom } from 'jotai'
|
||||
import { atomFamily, useAtomValue, useUpdateAtom } from 'jotai/utils'
|
||||
import { Album, AlbumArt, AlbumWithSongs, Artist, ArtistArt, ArtistInfo, Song } from '../models/music'
|
||||
import { SubsonicApiClient } from '../subsonic/api'
|
||||
import { AlbumID3Element, ArtistInfo2Element, ChildElement } from '../subsonic/elements'
|
||||
import { GetArtistResponse } from '../subsonic/responses'
|
||||
import { activeServerAtom } from './settings'
|
||||
import { Album, AlbumArt, AlbumWithSongs, Artist, ArtistArt, ArtistInfo, Song } from '@app/models/music'
|
||||
import { SubsonicApiClient } from '@app/subsonic/api'
|
||||
import { AlbumID3Element, ArtistInfo2Element, ChildElement } from '@app/subsonic/elements'
|
||||
import { GetArtistResponse } from '@app/subsonic/responses'
|
||||
import { activeServerAtom } from '@app/state/settings'
|
||||
|
||||
export const artistsAtom = atom<Artist[]>([])
|
||||
export const artistsUpdatingAtom = atom(false)
|
||||
@ -1,6 +1,6 @@
|
||||
import { atom } from 'jotai'
|
||||
import { AppSettings } from '../models/settings'
|
||||
import atomWithAsyncStorage from '../storage/atomWithAsyncStorage'
|
||||
import { AppSettings } from '@app/models/settings'
|
||||
import atomWithAsyncStorage from '@app/storage/atomWithAsyncStorage'
|
||||
|
||||
export const appSettingsAtom = atomWithAsyncStorage<AppSettings>('@appSettings', {
|
||||
servers: [],
|
||||
@ -3,8 +3,8 @@ import { atom } from 'jotai'
|
||||
import { useAtomValue, useUpdateAtom } from 'jotai/utils'
|
||||
import { useEffect } from 'react'
|
||||
import TrackPlayer, { State, Track } from 'react-native-track-player'
|
||||
import { Song } from '../models/music'
|
||||
import { PromiseQueue } from '../util'
|
||||
import { Song } from '@app/models/music'
|
||||
import PromiseQueue from '@app/util/PromiseQueue'
|
||||
|
||||
type TrackExt = Track & {
|
||||
id: string
|
||||
@ -1,5 +1,5 @@
|
||||
import { atomWithStorage } from 'jotai/utils'
|
||||
import { getItem, setItem } from './asyncstorage'
|
||||
import { getItem, setItem } from '@app/storage/asyncstorage'
|
||||
|
||||
export default <T>(key: string, defaultValue: T) => {
|
||||
return atomWithStorage<T>(key, defaultValue, {
|
||||
@ -1,5 +1,5 @@
|
||||
import { DownloadedSong } from '../models/music'
|
||||
import { getItem, multiGet, multiSet } from './asyncstorage'
|
||||
import { DownloadedSong } from '@app/models/music'
|
||||
import { getItem, multiGet, multiSet } from '@app/storage/asyncstorage'
|
||||
|
||||
const key = {
|
||||
downloadedSongKeys: '@downloadedSongKeys',
|
||||
@ -1,5 +1,5 @@
|
||||
import { TextStyle } from 'react-native'
|
||||
import colors from './colors'
|
||||
import colors from '@app/styles/colors'
|
||||
|
||||
export enum Font {
|
||||
regular = 'Metropolis-Regular',
|
||||
@ -11,7 +11,7 @@ import {
|
||||
GetIndexesParams,
|
||||
GetMusicDirectoryParams,
|
||||
StreamParams,
|
||||
} from './params'
|
||||
} from '@app/subsonic/params'
|
||||
import {
|
||||
GetAlbumList2Response,
|
||||
GetAlbumListResponse,
|
||||
@ -23,10 +23,10 @@ import {
|
||||
GetIndexesResponse,
|
||||
GetMusicDirectoryResponse,
|
||||
SubsonicResponse,
|
||||
} from './responses'
|
||||
import { Server } from '../models/settings'
|
||||
import paths from '../paths'
|
||||
import { PromiseQueue } from '../util'
|
||||
} from '@app/subsonic/responses'
|
||||
import { Server } from '@app/models/settings'
|
||||
import paths from '@app/util/paths'
|
||||
import PromiseQueue from '@app/util/PromiseQueue'
|
||||
|
||||
export class SubsonicApiError extends Error {
|
||||
method: string
|
||||
@ -1,6 +1,6 @@
|
||||
import { useAtomValue } from 'jotai/utils'
|
||||
import { activeServerAtom } from '../state/settings'
|
||||
import { SubsonicApiClient } from '../subsonic/api'
|
||||
import { activeServerAtom } from '@app/state/settings'
|
||||
import { SubsonicApiClient } from '@app/subsonic/api'
|
||||
|
||||
export const useSubsonicApi = () => {
|
||||
const activeServer = useAtomValue(activeServerAtom)
|
||||
@ -6,7 +6,7 @@ import {
|
||||
ArtistInfoElement,
|
||||
ChildElement,
|
||||
DirectoryElement,
|
||||
} from './elements'
|
||||
} from '@app/subsonic/elements'
|
||||
|
||||
export type ResponseStatus = 'ok' | 'failed'
|
||||
|
||||
@ -1,18 +1,6 @@
|
||||
export function formatDuration(seconds: number): string {
|
||||
const s = Math.floor(seconds) % 60
|
||||
const m = Math.floor(seconds / 60) % 60
|
||||
const h = Math.floor(seconds / 60 / 60)
|
||||
|
||||
let time = `${m.toString().padStart(1, '0')}:${s.toString().padStart(2, '0')}`
|
||||
if (h > 0) {
|
||||
time = `${h}:${time}`
|
||||
}
|
||||
return time
|
||||
}
|
||||
|
||||
type QueuedPromise = () => Promise<any>
|
||||
|
||||
export class PromiseQueue {
|
||||
class PromiseQueue {
|
||||
maxSimultaneously: number
|
||||
|
||||
private active = 0
|
||||
@ -39,3 +27,5 @@ export class PromiseQueue {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default PromiseQueue
|
||||
13
app/util/formatDuration.ts
Normal file
13
app/util/formatDuration.ts
Normal file
@ -0,0 +1,13 @@
|
||||
function formatDuration(seconds: number): string {
|
||||
const s = Math.floor(seconds) % 60
|
||||
const m = Math.floor(seconds / 60) % 60
|
||||
const h = Math.floor(seconds / 60 / 60)
|
||||
|
||||
let time = `${m.toString().padStart(1, '0')}:${s.toString().padStart(2, '0')}`
|
||||
if (h > 0) {
|
||||
time = `${h}:${time}`
|
||||
}
|
||||
return time
|
||||
}
|
||||
|
||||
export default formatDuration
|
||||
@ -1,6 +1,16 @@
|
||||
module.exports = {
|
||||
presets: ['module:metro-react-native-babel-preset'],
|
||||
plugins: [
|
||||
[
|
||||
require.resolve('babel-plugin-module-resolver'),
|
||||
{
|
||||
cwd: 'babelrc',
|
||||
extensions: ['.ts', '.tsx', '.js', '.ios.js', '.android.js'],
|
||||
alias: {
|
||||
'@app': './app',
|
||||
},
|
||||
},
|
||||
],
|
||||
// reanimated has to be listed last in plugins
|
||||
'react-native-reanimated/plugin',
|
||||
],
|
||||
|
||||
6
index.js
6
index.js
@ -5,12 +5,12 @@ import { enableScreens } from 'react-native-screens'
|
||||
enableScreens()
|
||||
|
||||
import { AppRegistry } from 'react-native'
|
||||
import App from './App'
|
||||
import { name as appName } from './app.json'
|
||||
import App from '@app/App'
|
||||
import { name as appName } from '@app/app.json'
|
||||
import TrackPlayer, { Capability } from 'react-native-track-player'
|
||||
|
||||
AppRegistry.registerComponent(appName, () => App)
|
||||
TrackPlayer.registerPlaybackService(() => require('./src/playback/service'))
|
||||
TrackPlayer.registerPlaybackService(() => require('./app/service'))
|
||||
|
||||
async function start() {
|
||||
await TrackPlayer.setupPlayer()
|
||||
|
||||
@ -48,6 +48,7 @@
|
||||
"@types/uuid": "^8.3.0",
|
||||
"@types/xmldom": "^0.1.30",
|
||||
"babel-jest": "^26.6.3",
|
||||
"babel-plugin-module-resolver": "^4.1.0",
|
||||
"eslint": "^7.14.0",
|
||||
"jest": "^26.6.3",
|
||||
"metro-react-native-babel-preset": "^0.64.0",
|
||||
|
||||
@ -1,30 +0,0 @@
|
||||
import React from 'react'
|
||||
import { Image, ImageSourcePropType } from 'react-native'
|
||||
import colors from '../styles/colors'
|
||||
|
||||
export type FocusableIconProps = {
|
||||
focused: boolean
|
||||
source: ImageSourcePropType
|
||||
focusedSource?: ImageSourcePropType
|
||||
width?: number
|
||||
height?: number
|
||||
}
|
||||
|
||||
const FocusableIcon: React.FC<FocusableIconProps> = props => {
|
||||
props.focusedSource = props.focusedSource || props.source
|
||||
props.width = props.width || 26
|
||||
props.height = props.height || 26
|
||||
|
||||
return (
|
||||
<Image
|
||||
style={{
|
||||
height: props.height,
|
||||
width: props.width,
|
||||
tintColor: props.focused ? colors.text.primary : colors.text.secondary,
|
||||
}}
|
||||
source={props.focused ? props.focusedSource : props.source}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export default FocusableIcon
|
||||
@ -1,71 +0,0 @@
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import { GestureResponderEvent, LayoutRectangle, Pressable, ViewStyle } from 'react-native'
|
||||
import FastImage, { Source } from 'react-native-fast-image'
|
||||
|
||||
const PressableImage: React.FC<{
|
||||
source: Source | number
|
||||
onPress?: (event: GestureResponderEvent) => void
|
||||
style?: ViewStyle
|
||||
tintColor?: string
|
||||
disabled?: boolean
|
||||
hitSlop?: number
|
||||
padding?: number
|
||||
ripple?: boolean
|
||||
}> = ({ source, onPress, style, tintColor, disabled, hitSlop, padding, ripple }) => {
|
||||
const [opacity, setOpacity] = useState(1)
|
||||
const [dimensions, setDimensions] = useState<LayoutRectangle | undefined>(undefined)
|
||||
|
||||
disabled = disabled === undefined ? false : disabled
|
||||
padding = padding || 0
|
||||
ripple = ripple === undefined ? false : ripple
|
||||
style = {
|
||||
...(style || {}),
|
||||
opacity,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
disabled ? setOpacity(0.3) : setOpacity(1)
|
||||
}, [disabled])
|
||||
|
||||
return (
|
||||
<Pressable
|
||||
style={style}
|
||||
onPress={onPress}
|
||||
disabled={disabled}
|
||||
hitSlop={hitSlop}
|
||||
android_ripple={
|
||||
ripple
|
||||
? {
|
||||
color: 'rgba(255,255,255,0.26)',
|
||||
radius: dimensions ? dimensions.width / 2 : undefined,
|
||||
}
|
||||
: undefined
|
||||
}
|
||||
onPressIn={() => {
|
||||
if (!disabled) {
|
||||
setOpacity(0.4)
|
||||
}
|
||||
}}
|
||||
onPressOut={() => {
|
||||
if (!disabled) {
|
||||
setOpacity(1)
|
||||
}
|
||||
}}
|
||||
onLayout={event => setDimensions(event.nativeEvent.layout)}>
|
||||
<FastImage
|
||||
style={{
|
||||
display: dimensions ? 'flex' : 'none',
|
||||
height: dimensions ? dimensions.height - padding : 0,
|
||||
width: dimensions ? dimensions.width - padding : 0,
|
||||
}}
|
||||
source={source}
|
||||
tintColor={tintColor || 'white'}
|
||||
resizeMode={FastImage.resizeMode.contain}
|
||||
/>
|
||||
</Pressable>
|
||||
)
|
||||
}
|
||||
|
||||
export default PressableImage
|
||||
@ -1,16 +0,0 @@
|
||||
import React from 'react'
|
||||
import LinearGradient from 'react-native-linear-gradient'
|
||||
import colors from '../../styles/colors'
|
||||
|
||||
const TopTabContainer: React.FC<{}> = ({ children }) => (
|
||||
<LinearGradient
|
||||
colors={[colors.gradient.high, colors.gradient.mid, colors.gradient.low]}
|
||||
locations={[0.03, 0.3, 0.7]}
|
||||
style={{
|
||||
flex: 1,
|
||||
}}>
|
||||
{children}
|
||||
</LinearGradient>
|
||||
)
|
||||
|
||||
export default TopTabContainer
|
||||
@ -36,8 +36,10 @@
|
||||
|
||||
/* Module Resolution Options */
|
||||
"moduleResolution": "node" /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */,
|
||||
// "baseUrl": "./", /* Base directory to resolve non-absolute module names. */
|
||||
// "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
|
||||
"baseUrl": "./", /* Base directory to resolve non-absolute module names. */
|
||||
"paths": {
|
||||
"@app/*": ["app/*/index", "app/*"]
|
||||
}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
|
||||
// "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
|
||||
// "typeRoots": [], /* List of folders to include type definitions from. */
|
||||
// "types": [], /* Type declaration files to be included in compilation. */
|
||||
|
||||
38
yarn.lock
38
yarn.lock
@ -1765,6 +1765,17 @@ babel-plugin-jest-hoist@^26.6.2:
|
||||
"@types/babel__core" "^7.0.0"
|
||||
"@types/babel__traverse" "^7.0.6"
|
||||
|
||||
babel-plugin-module-resolver@^4.1.0:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-plugin-module-resolver/-/babel-plugin-module-resolver-4.1.0.tgz#22a4f32f7441727ec1fbf4967b863e1e3e9f33e2"
|
||||
integrity sha512-MlX10UDheRr3lb3P0WcaIdtCSRlxdQsB1sBqL7W0raF070bGl1HQQq5K3T2vf2XAYie+ww+5AKC/WrkjRO2knA==
|
||||
dependencies:
|
||||
find-babel-config "^1.2.0"
|
||||
glob "^7.1.6"
|
||||
pkg-up "^3.1.0"
|
||||
reselect "^4.0.0"
|
||||
resolve "^1.13.1"
|
||||
|
||||
babel-plugin-polyfill-corejs2@^0.2.2:
|
||||
version "0.2.2"
|
||||
resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.2.2.tgz#e9124785e6fd94f94b618a7954e5693053bf5327"
|
||||
@ -3019,6 +3030,14 @@ finalhandler@1.1.2:
|
||||
statuses "~1.5.0"
|
||||
unpipe "~1.0.0"
|
||||
|
||||
find-babel-config@^1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/find-babel-config/-/find-babel-config-1.2.0.tgz#a9b7b317eb5b9860cda9d54740a8c8337a2283a2"
|
||||
integrity sha512-jB2CHJeqy6a820ssiqwrKMeyC6nNdmrcgkKWJWmpoxpE8RKciYJXCcXRq1h2AzCo5I5BJeN2tkGEO3hLTuePRA==
|
||||
dependencies:
|
||||
json5 "^0.5.1"
|
||||
path-exists "^3.0.0"
|
||||
|
||||
find-cache-dir@^2.0.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-2.1.0.tgz#8d0f94cd13fe43c6c7c261a0d86115ca918c05f7"
|
||||
@ -4241,6 +4260,11 @@ json-stable-stringify-without-jsonify@^1.0.1:
|
||||
resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651"
|
||||
integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=
|
||||
|
||||
json5@^0.5.1:
|
||||
version "0.5.1"
|
||||
resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821"
|
||||
integrity sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=
|
||||
|
||||
json5@^2.1.2:
|
||||
version "2.2.0"
|
||||
resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.0.tgz#2dfefe720c6ba525d9ebd909950f0515316c89a3"
|
||||
@ -5314,6 +5338,13 @@ pkg-dir@^4.2.0:
|
||||
dependencies:
|
||||
find-up "^4.0.0"
|
||||
|
||||
pkg-up@^3.1.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/pkg-up/-/pkg-up-3.1.0.tgz#100ec235cc150e4fd42519412596a28512a0def5"
|
||||
integrity sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==
|
||||
dependencies:
|
||||
find-up "^3.0.0"
|
||||
|
||||
plist@^3.0.1:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/plist/-/plist-3.0.2.tgz#74bbf011124b90421c22d15779cee60060ba95bc"
|
||||
@ -5768,6 +5799,11 @@ require-main-filename@^2.0.0:
|
||||
resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b"
|
||||
integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==
|
||||
|
||||
reselect@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/reselect/-/reselect-4.0.0.tgz#f2529830e5d3d0e021408b246a206ef4ea4437f7"
|
||||
integrity sha512-qUgANli03jjAyGlnbYVAV5vvnOmJnODyABz51RdBN7M4WaVu8mecZWgyQNkG8Yqe3KRGRt0l4K4B3XVEULC4CA==
|
||||
|
||||
resolve-cwd@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d"
|
||||
@ -5795,7 +5831,7 @@ resolve-url@^0.2.1:
|
||||
resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a"
|
||||
integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=
|
||||
|
||||
resolve@^1.1.6, resolve@^1.10.0, resolve@^1.12.0, resolve@^1.14.2, resolve@^1.18.1:
|
||||
resolve@^1.1.6, resolve@^1.10.0, resolve@^1.12.0, resolve@^1.13.1, resolve@^1.14.2, resolve@^1.18.1:
|
||||
version "1.20.0"
|
||||
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975"
|
||||
integrity sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user