Compare commits

..

5 Commits

Author SHA1 Message Date
Lei Nelissen
1edeb00631 Fix active button color on Android 2021-04-03 15:19:38 +02:00
Lei Nelissen
d422c1ff1e Pull current track from Redux store
Fixes #40
2021-04-03 14:49:49 +02:00
Lei Nelissen
28b330ad4c Update all dependencies 2021-04-03 14:49:01 +02:00
Lei Nelissen
a867513212 Update Fastlane Sentry plugin 2021-03-22 09:49:33 +01:00
Lei Nelissen
14a6341fae Release build 13 2021-03-22 09:24:36 +01:00
14 changed files with 668 additions and 401 deletions

View File

@@ -6,21 +6,21 @@ GEM
public_suffix (>= 2.0.2, < 5.0)
artifactory (3.0.15)
atomos (0.1.3)
aws-eventstream (1.1.0)
aws-partitions (1.426.0)
aws-sdk-core (3.112.0)
aws-eventstream (1.1.1)
aws-partitions (1.434.0)
aws-sdk-core (3.113.0)
aws-eventstream (~> 1, >= 1.0.2)
aws-partitions (~> 1, >= 1.239.0)
aws-sigv4 (~> 1.1)
jmespath (~> 1.0)
aws-sdk-kms (1.42.0)
aws-sdk-kms (1.43.0)
aws-sdk-core (~> 3, >= 3.112.0)
aws-sigv4 (~> 1.1)
aws-sdk-s3 (1.88.0)
aws-sdk-s3 (1.92.0)
aws-sdk-core (~> 3, >= 3.112.0)
aws-sdk-kms (~> 1)
aws-sigv4 (~> 1.1)
aws-sigv4 (1.2.2)
aws-sigv4 (1.2.3)
aws-eventstream (~> 1, >= 1.0.2)
babosa (1.0.4)
claide (1.0.3)
@@ -35,7 +35,7 @@ GEM
domain_name (0.5.20190701)
unf (>= 0.0.5, < 1.0.0)
dotenv (2.7.6)
emoji_regex (3.2.1)
emoji_regex (3.2.2)
excon (0.79.0)
faraday (1.3.0)
faraday-net_http (~> 1.0)
@@ -47,8 +47,8 @@ GEM
faraday-net_http (1.0.1)
faraday_middleware (1.0.0)
faraday (~> 1.0)
fastimage (2.2.2)
fastlane (2.174.0)
fastimage (2.2.3)
fastlane (2.178.0)
CFPropertyList (>= 2.3, < 4.0.0)
addressable (>= 2.3, < 3.0.0)
artifactory (~> 3.0)
@@ -72,6 +72,7 @@ GEM
jwt (>= 2.1.0, < 3)
mini_magick (>= 4.9.4, < 5.0.0)
multipart-post (~> 2.0.0)
naturally (~> 2.2)
plist (>= 3.1.0, < 4.0.0)
rubyzip (>= 2.0.0, < 3.0.0)
security (= 0.1.3)
@@ -85,7 +86,7 @@ GEM
xcodeproj (>= 1.13.0, < 2.0.0)
xcpretty (~> 0.3.0)
xcpretty-travis-formatter (>= 0.0.3)
fastlane-plugin-sentry (1.8.0)
fastlane-plugin-sentry (1.8.1)
gh_inspector (1.1.3)
google-api-client (0.38.0)
addressable (~> 2.5, >= 2.5.1)
@@ -95,7 +96,7 @@ GEM
representable (~> 3.0)
retriable (>= 2.0, < 4.0)
signet (~> 0.12)
google-apis-core (0.2.1)
google-apis-core (0.3.0)
addressable (~> 2.5, >= 2.5.1)
googleauth (~> 0.14)
httpclient (>= 2.8.1, < 3.0)
@@ -105,17 +106,17 @@ GEM
rexml
signet (~> 0.14)
webrick
google-apis-iamcredentials_v1 (0.1.0)
google-apis-iamcredentials_v1 (0.2.0)
google-apis-core (~> 0.1)
google-apis-storage_v1 (0.2.0)
google-apis-storage_v1 (0.3.0)
google-apis-core (~> 0.1)
google-cloud-core (1.5.0)
google-cloud-core (1.6.0)
google-cloud-env (~> 1.0)
google-cloud-errors (~> 1.0)
google-cloud-env (1.4.0)
google-cloud-env (1.5.0)
faraday (>= 0.17.3, < 2.0)
google-cloud-errors (1.0.1)
google-cloud-storage (1.30.0)
google-cloud-errors (1.1.0)
google-cloud-storage (1.31.0)
addressable (~> 2.5)
digest-crc (~> 0.4)
google-apis-iamcredentials_v1 (~> 0.1)
@@ -123,7 +124,7 @@ GEM
google-cloud-core (~> 1.2)
googleauth (~> 0.9)
mini_mime (~> 1.0)
googleauth (0.15.1)
googleauth (0.16.0)
faraday (>= 0.17.3, < 2.0)
jwt (>= 1.4, < 3.0)
memoist (~> 0.16)
@@ -158,7 +159,7 @@ GEM
ruby2_keywords (0.0.4)
rubyzip (2.3.0)
security (0.1.3)
signet (0.14.1)
signet (0.15.0)
addressable (~> 2.3)
faraday (>= 0.17.3, < 2.0)
jwt (>= 1.5, < 3.0)

View File

@@ -542,7 +542,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 12;
CURRENT_PROJECT_VERSION = 13;
DEVELOPMENT_TEAM = 238P3C58WC;
ENABLE_BITCODE = NO;
GCC_PREPROCESSOR_DEFINITIONS = (
@@ -573,7 +573,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 12;
CURRENT_PROJECT_VERSION = 13;
DEVELOPMENT_TEAM = 238P3C58WC;
INFOPLIST_FILE = JellyfinAudioPlayer/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";

View File

@@ -21,7 +21,7 @@
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>12</string>
<string>13</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>NSAppTransportSecurity</key>

View File

@@ -19,6 +19,6 @@
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>12</string>
<string>13</string>
</dict>
</plist>

View File

@@ -261,13 +261,15 @@ PODS:
- React-jsi (= 0.64.0)
- React-perflogger (= 0.64.0)
- React-jsinspector (0.64.0)
- react-native-airplay-button (1.0.4):
- React-Core
- react-native-safe-area-context (3.2.0):
- React-Core
- react-native-slider (3.0.3):
- React
- react-native-track-player (1.2.3):
- react-native-track-player (1.2.6):
- React
- react-native-webview (11.2.3):
- react-native-webview (11.3.1):
- React-Core
- React-perflogger (0.64.0)
- React-RCTActionSheet (0.64.0):
@@ -433,6 +435,7 @@ DEPENDENCIES:
- React-jsi (from `../node_modules/react-native/ReactCommon/jsi`)
- React-jsiexecutor (from `../node_modules/react-native/ReactCommon/jsiexecutor`)
- React-jsinspector (from `../node_modules/react-native/ReactCommon/jsinspector`)
- react-native-airplay-button (from `../node_modules/react-native-airplay-button`)
- react-native-safe-area-context (from `../node_modules/react-native-safe-area-context`)
- "react-native-slider (from `../node_modules/@react-native-community/slider`)"
- react-native-track-player (from `../node_modules/react-native-track-player`)
@@ -511,6 +514,8 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native/ReactCommon/jsiexecutor"
React-jsinspector:
:path: "../node_modules/react-native/ReactCommon/jsinspector"
react-native-airplay-button:
:path: "../node_modules/react-native-airplay-button"
react-native-safe-area-context:
:path: "../node_modules/react-native-safe-area-context"
react-native-slider:
@@ -594,10 +599,11 @@ SPEC CHECKSUMS:
React-jsi: 74341196d9547cbcbcfa4b3bbbf03af56431d5a1
React-jsiexecutor: 06a9c77b56902ae7ffcdd7a4905f664adc5d237b
React-jsinspector: 0ae35a37b20d5e031eb020a69cc5afdbd6406301
react-native-airplay-button: 6899e488bff6b4d87b33c1def54c919dad2e3803
react-native-safe-area-context: e471852c5ed67eea4b10c5d9d43c1cebae3b231d
react-native-slider: b733e17fdd31186707146debf1f04b5d94aa1a93
react-native-track-player: ba2416753b58f3cdf9db5a07daa65876d659f925
react-native-webview: 36561eaf7508e67f72d8c959b713bac841f3652e
react-native-track-player: 92eaa90aeb24ce1a7149f983c75128075004e7a2
react-native-webview: 30f048378c6cee522ed9bbbedbc34acb21e58188
React-perflogger: 9c547d8f06b9bf00cb447f2b75e8d7f19b7e02af
React-RCTActionSheet: 3080b6e12e0e1a5b313c8c0050699b5c794a1b11
React-RCTAnimation: 3f96f21a497ae7dabf4d2f150ee43f906aaf516f

836
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -19,8 +19,8 @@
"@react-navigation/bottom-tabs": "^5.11.8",
"@react-navigation/native": "^5.9.3",
"@react-navigation/stack": "^5.14.3",
"@reduxjs/toolkit": "^1.5.0",
"@sentry/react-native": "^2.3.0",
"@reduxjs/toolkit": "^1.5.1",
"@sentry/react-native": "^2.4.0",
"@types/lodash": "^4.14.168",
"date-fns": "^2.19.0",
"fuse.js": "^6.4.6",
@@ -34,41 +34,41 @@
"react-native-fast-image": "^8.3.4",
"react-native-gesture-handler": "^1.10.3",
"react-native-localize": "^2.0.2",
"react-native-reanimated": "^2.0.0",
"react-native-reanimated": "^2.1.0",
"react-native-safe-area-context": "^3.2.0",
"react-native-screens": "^2.18.1",
"react-native-svg": "^12.1.0",
"react-native-svg-transformer": "^0.14.3",
"react-native-track-player": "^1.2.6",
"react-native-webview": "^11.3.1",
"react-redux": "^7.2.2",
"react-native-track-player": "^1.2.7",
"react-native-webview": "^11.3.2",
"react-redux": "^7.2.3",
"redux": "^4.0.5",
"redux-logger": "^3.0.6",
"redux-persist": "^6.0.0",
"styled-components": "^5.2.1"
"styled-components": "^5.2.3"
},
"devDependencies": {
"@babel/core": "^7.13.10",
"@babel/core": "^7.13.14",
"@babel/runtime": "^7.13.10",
"@react-native-community/eslint-config": "^2.0.0",
"@sentry/cli": "^1.63.1",
"@sentry/cli": "^1.63.2",
"@types/i18n-js": "^3.8.0",
"@types/jest": "^26.0.21",
"@types/react-native": "^0.64.0",
"@types/jest": "^26.0.22",
"@types/react-native": "^0.64.2",
"@types/react-redux": "^7.1.16",
"@types/react-test-renderer": "^17.0.1",
"@types/redux-logger": "^3.0.8",
"@types/styled-components": "^5.1.9",
"@types/styled-components-react-native": "^5.1.1",
"@typescript-eslint/eslint-plugin": "^4.18.0",
"@typescript-eslint/parser": "^4.18.0",
"@typescript-eslint/eslint-plugin": "^4.20.0",
"@typescript-eslint/parser": "^4.20.0",
"babel-jest": "^26.6.3",
"babel-plugin-module-resolver": "^4.1.0",
"eslint": "^7.22.0",
"eslint": "^7.23.0",
"eslint-plugin-react-hooks": "^4.2.0",
"jest": "^26.6.3",
"metro-react-native-babel-preset": "^0.65.2",
"react-test-renderer": "^17.0.1",
"react-test-renderer": "^17.0.2",
"typescript": "^4.2.3"
},
"jest": {

View File

@@ -11,7 +11,8 @@ import {
} from '@react-navigation/native';
import { useColorScheme } from 'react-native';
import { ColorSchemeContext, themes } from './Colors';
import ErrorReportingAlert from 'utility/ErrorReportingAlert';
// import ErrorReportingAlert from 'utility/ErrorReportingAlert';
import PlayerStateUpdater from './PlayerStateUpdater';
export default function App(): JSX.Element {
const colorScheme = useColorScheme();
@@ -41,6 +42,7 @@ export default function App(): JSX.Element {
<ColorSchemeContext.Provider value={theme}>
<NavigationContainer theme={colorScheme === 'dark' ? DarkTheme : DefaultTheme}>
<Routes />
<PlayerStateUpdater />
</NavigationContainer>
</ColorSchemeContext.Provider>
</PersistGate>

View File

@@ -13,21 +13,14 @@ interface ButtonProps extends PressableProps {
style?: ViewProps['style'];
}
interface PressableStyleProps {
active: boolean;
}
const BaseButton = styled.Pressable<PressableStyleProps>`
const BaseButton = styled.Pressable`
padding: 16px;
border-radius: 8px;
flex-direction: row;
align-items: center;
justify-content: center;
flex-grow: 1;
${props => props.active && css`
background-color: ${THEME_COLOR};
`}
`;
const ButtonText = styled.Text<{ active?: boolean }>`
@@ -51,8 +44,10 @@ export default function Button(props: ButtonProps) {
{...rest}
onPressIn={handlePressIn}
onPressOut={handlePressOut}
active={isPressed}
style={[ defaultStyles.button, props.style ]}
style={[
props.style,
{ backgroundColor: isPressed ? THEME_COLOR : defaultStyles.button.backgroundColor }
]}
>
{Icon &&
<Icon

View File

@@ -0,0 +1,54 @@
import { useCallback, useEffect } from 'react';
import TrackPlayer, { TrackPlayerEvents } from 'react-native-track-player';
import { shallowEqual, useDispatch } from 'react-redux';
import { useTypedSelector } from 'store';
import player from 'store/player';
function PlayerStateUpdater() {
const dispatch = useDispatch();
const trackId = useTypedSelector(state => state.player.currentTrack?.id, shallowEqual);
const handleUpdate = useCallback(async () => {
const currentTrackId = await TrackPlayer.getCurrentTrack();
// GUARD: Only retrieve new track if it is different from the one we
// have currently in state.
if (currentTrackId === trackId){
return;
}
// GUARD: Only fetch current track if there is a current track
if (!currentTrackId) {
dispatch(player.actions.setCurrentTrack(undefined));
}
// If it is different, retrieve the track and save it
try {
const currentTrack = await TrackPlayer.getTrack(currentTrackId);
dispatch(player.actions.setCurrentTrack(currentTrack));
} catch {
// Due to the async nature, a track might be removed at the
// point when we try to retrieve it. If this happens, we'll just
// smother the error and wait for a new track update to
// finish.
}
}, [trackId, dispatch]);
useEffect(() => {
function handler() {
handleUpdate();
}
handler();
const subscription = TrackPlayer.addEventListener(TrackPlayerEvents.PLAYBACK_TRACK_CHANGED, handler);
return () => {
subscription.remove();
};
}, []);
return null;
}
export default PlayerStateUpdater;

View File

@@ -80,7 +80,7 @@ const Album: React.FC = () => {
const refresh = useCallback(() => { dispatch(fetchTracksByAlbum(id)); }, [id, dispatch]);
const selectTrack = useCallback(async (trackId) => {
const tracks = await playAlbum(id, false);
if (tracks) {
const track = tracks.find((t) => t.id.startsWith(trackId));

View File

@@ -1,10 +1,26 @@
import { createSlice } from '@reduxjs/toolkit';
import { createSlice, PayloadAction } from '@reduxjs/toolkit';
import { Track } from 'react-native-track-player';
interface State {
addedTrackCount: number,
currentTrack: Track | undefined,
}
const initialState: State = {
addedTrackCount: 0,
currentTrack: undefined,
};
const player = createSlice({
name: 'player',
initialState: 0,
initialState,
reducers: {
addNewTrackToPlayer: (state) => state + 1,
addNewTrackToPlayer: (state) => {
state.addedTrackCount += 1;
},
setCurrentTrack: (state, action: PayloadAction<Track | undefined>) => {
state.currentTrack = action.payload;
},
}
});

View File

@@ -1,42 +1,15 @@
import { useEffect, useState } from 'react';
import TrackPlayer, { usePlaybackState, Track } from 'react-native-track-player';
import { Track } from 'react-native-track-player';
import { useTypedSelector } from 'store';
const idEqual = (left: Track | undefined, right: Track | undefined) => {
return left?.id === right?.id;
};
/**
* This hook retrieves the current playing track from TrackPlayer
*/
export default function useCurrentTrack(): Track | undefined {
const state = usePlaybackState();
const [track, setTrack] = useState<Track>();
useEffect(() => {
const fetchTrack = async () => {
const currentTrackId = await TrackPlayer.getCurrentTrack();
// GUARD: Only fetch current track if there is a current track
if (!currentTrackId) {
setTrack(undefined);
}
// GUARD: Only retrieve new track if it is different from the one we
// have currently in state.
if (currentTrackId === track?.id){
return;
}
// If it is different, retrieve the track and save it
try {
const currentTrack = await TrackPlayer.getTrack(currentTrackId);
setTrack(currentTrack);
} catch {
// Due to the async nature, a track might be removed at the
// point when we try to retrieve it. If this happens, we'll just
// smother the error and wait for a new track update to
// finish.
}
};
fetchTrack();
}, [state, track, setTrack]);
const track = useTypedSelector(state => state.player.currentTrack, idEqual);
return track;
}

View File

@@ -8,7 +8,7 @@ import { useTypedSelector } from 'store';
export default function useQueue(): Track[] {
const state = usePlaybackState();
const [queue, setQueue] = useState<Track[]>([]);
const addedTrackCount = useTypedSelector(state => state.player);
const addedTrackCount = useTypedSelector(state => state.player.addedTrackCount);
useEffect(() => {
TrackPlayer.getQueue().then(setQueue);