mirror of
https://github.com/Boof2015/astra-mobile.git
synced 2026-08-12 05:10:52 +02:00
minor ui/ux stuff
This commit is contained in:
@@ -11,7 +11,7 @@ export default function TabsLayout() {
|
|||||||
const colors = useColors();
|
const colors = useColors();
|
||||||
return (
|
return (
|
||||||
<Tabs
|
<Tabs
|
||||||
detachInactiveScreens
|
detachInactiveScreens={false}
|
||||||
screenOptions={{
|
screenOptions={{
|
||||||
headerShown: false,
|
headerShown: false,
|
||||||
freezeOnBlur: false,
|
freezeOnBlur: false,
|
||||||
|
|||||||
@@ -89,7 +89,8 @@ export default function EQScreen() {
|
|||||||
const { width: windowWidth, height: windowHeight } = useWindowDimensions();
|
const { width: windowWidth, height: windowHeight } = useWindowDimensions();
|
||||||
const insets = useSafeAreaInsets();
|
const insets = useSafeAreaInsets();
|
||||||
const availableWidth = windowWidth - insets.left - insets.right;
|
const availableWidth = windowWidth - insets.left - insets.right;
|
||||||
const isWide = isWideWindow(availableWidth, windowHeight - insets.top - insets.bottom);
|
const availableHeight = windowHeight - insets.top - insets.bottom;
|
||||||
|
const isWide = isWideWindow(availableWidth, availableHeight);
|
||||||
// Editing pane keeps a phone-ish width; the graph gets everything else.
|
// Editing pane keeps a phone-ish width; the graph gets everything else.
|
||||||
const sidePaneWidth = Math.min(360, Math.max(280, Math.round(availableWidth * 0.4)));
|
const sidePaneWidth = Math.min(360, Math.max(280, Math.round(availableWidth * 0.4)));
|
||||||
|
|
||||||
@@ -273,7 +274,7 @@ export default function EQScreen() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const bottomBarEl = (
|
const bottomBarEl = (
|
||||||
<View style={[styles.bottomBar, isWide && styles.bottomBarWide]}>
|
<View style={[styles.bottomBar, !isWide && styles.bottomBarNarrow, isWide && styles.bottomBarWide]}>
|
||||||
<View style={styles.preamp}>
|
<View style={styles.preamp}>
|
||||||
<EQSlider
|
<EQSlider
|
||||||
label="Preamp"
|
label="Preamp"
|
||||||
@@ -660,7 +661,7 @@ const useStyles = createThemedStyles((colors) => ({
|
|||||||
},
|
},
|
||||||
graphWrap: {
|
graphWrap: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
minHeight: 180,
|
minHeight: 168,
|
||||||
marginHorizontal: spacing.lg,
|
marginHorizontal: spacing.lg,
|
||||||
},
|
},
|
||||||
section: {
|
section: {
|
||||||
@@ -697,6 +698,9 @@ const useStyles = createThemedStyles((colors) => ({
|
|||||||
paddingTop: spacing.md,
|
paddingTop: spacing.md,
|
||||||
paddingBottom: spacing.sm,
|
paddingBottom: spacing.sm,
|
||||||
},
|
},
|
||||||
|
bottomBarNarrow: {
|
||||||
|
paddingTop: spacing.xs,
|
||||||
|
},
|
||||||
preamp: {
|
preamp: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
},
|
},
|
||||||
|
|||||||
+1
-1
@@ -363,7 +363,7 @@ export default function RootLayout() {
|
|||||||
presentation: 'transparentModal',
|
presentation: 'transparentModal',
|
||||||
animation: 'none',
|
animation: 'none',
|
||||||
gestureEnabled: false,
|
gestureEnabled: false,
|
||||||
contentStyle: { backgroundColor: 'transparent' },
|
contentStyle: { backgroundColor: theme.colors.bgPrimary },
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</Stack>
|
</Stack>
|
||||||
|
|||||||
@@ -1064,7 +1064,7 @@ export default function NowPlayingScreen() {
|
|||||||
const useStyles = createThemedStyles((colors) => ({
|
const useStyles = createThemedStyles((colors) => ({
|
||||||
backdrop: {
|
backdrop: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
backgroundColor: 'transparent',
|
backgroundColor: colors.bgPrimary,
|
||||||
},
|
},
|
||||||
content: {
|
content: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
|
|||||||
@@ -75,6 +75,7 @@ const PLAYLIST_RESULT_LIMIT = 4;
|
|||||||
const EMPTY_RECENT_TRACKS_LIMIT = 3;
|
const EMPTY_RECENT_TRACKS_LIMIT = 3;
|
||||||
const ALL_TRACK_RESULT_LIMIT = 120;
|
const ALL_TRACK_RESULT_LIMIT = 120;
|
||||||
const ALL_ENTITY_RESULT_LIMIT = 80;
|
const ALL_ENTITY_RESULT_LIMIT = 80;
|
||||||
|
const QUEUED_FEEDBACK_MS = 1000;
|
||||||
|
|
||||||
const NAV_ENTRIES: {
|
const NAV_ENTRIES: {
|
||||||
id: string;
|
id: string;
|
||||||
@@ -470,12 +471,14 @@ function ResultRow({
|
|||||||
result,
|
result,
|
||||||
query,
|
query,
|
||||||
active,
|
active,
|
||||||
|
queued,
|
||||||
onPress,
|
onPress,
|
||||||
onQueueTrack,
|
onQueueTrack,
|
||||||
}: {
|
}: {
|
||||||
result: SearchResult;
|
result: SearchResult;
|
||||||
query: string;
|
query: string;
|
||||||
active: boolean;
|
active: boolean;
|
||||||
|
queued: boolean;
|
||||||
onPress: () => void;
|
onPress: () => void;
|
||||||
onQueueTrack: (track: DbTrack) => void;
|
onQueueTrack: (track: DbTrack) => void;
|
||||||
}) {
|
}) {
|
||||||
@@ -513,7 +516,7 @@ function ResultRow({
|
|||||||
accessibilityRole="button"
|
accessibilityRole="button"
|
||||||
accessibilityLabel={`Play ${result.track.title} next`}
|
accessibilityLabel={`Play ${result.track.title} next`}
|
||||||
>
|
>
|
||||||
<Ionicons name="add" size={18} color={colors.accentTextStrong} />
|
<Ionicons name={queued ? 'checkmark' : 'add'} size={18} color={colors.accentTextStrong} />
|
||||||
</Pressable>
|
</Pressable>
|
||||||
) : result.kind === 'playlist' && result.playlist.remote ? (
|
) : result.kind === 'playlist' && result.playlist.remote ? (
|
||||||
<Ionicons name="cloud" size={14} color={colors.accent} />
|
<Ionicons name="cloud" size={14} color={colors.accent} />
|
||||||
@@ -550,6 +553,8 @@ function QuickSearchPanel({
|
|||||||
|
|
||||||
const [query, setQuery] = useState(initialQuery);
|
const [query, setQuery] = useState(initialQuery);
|
||||||
const [showAllLibrary, setShowAllLibrary] = useState(false);
|
const [showAllLibrary, setShowAllLibrary] = useState(false);
|
||||||
|
const [queuedTrackPaths, setQueuedTrackPaths] = useState<Set<string>>(() => new Set());
|
||||||
|
const queuedFeedbackTimers = useRef(new Map<string, ReturnType<typeof setTimeout>>());
|
||||||
const trimmedQuery = query.trim();
|
const trimmedQuery = query.trim();
|
||||||
const hasQuery = trimmedQuery.length > 0;
|
const hasQuery = trimmedQuery.length > 0;
|
||||||
|
|
||||||
@@ -558,6 +563,14 @@ function QuickSearchPanel({
|
|||||||
return () => clearTimeout(timer);
|
return () => clearTimeout(timer);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
useEffect(
|
||||||
|
() => () => {
|
||||||
|
queuedFeedbackTimers.current.forEach(clearTimeout);
|
||||||
|
queuedFeedbackTimers.current.clear();
|
||||||
|
},
|
||||||
|
[]
|
||||||
|
);
|
||||||
|
|
||||||
const updateQuery = (value: string) => {
|
const updateQuery = (value: string) => {
|
||||||
setQuery(value);
|
setQuery(value);
|
||||||
setShowAllLibrary(false);
|
setShowAllLibrary(false);
|
||||||
@@ -930,6 +943,27 @@ function QuickSearchPanel({
|
|||||||
|
|
||||||
const queueTrack = (track: DbTrack) => {
|
const queueTrack = (track: DbTrack) => {
|
||||||
commitHaptic();
|
commitHaptic();
|
||||||
|
const existingTimer = queuedFeedbackTimers.current.get(track.path);
|
||||||
|
if (existingTimer) clearTimeout(existingTimer);
|
||||||
|
|
||||||
|
setQueuedTrackPaths((current) => {
|
||||||
|
if (current.has(track.path)) return current;
|
||||||
|
const next = new Set(current);
|
||||||
|
next.add(track.path);
|
||||||
|
return next;
|
||||||
|
});
|
||||||
|
|
||||||
|
const feedbackTimer = setTimeout(() => {
|
||||||
|
queuedFeedbackTimers.current.delete(track.path);
|
||||||
|
setQueuedTrackPaths((current) => {
|
||||||
|
if (!current.has(track.path)) return current;
|
||||||
|
const next = new Set(current);
|
||||||
|
next.delete(track.path);
|
||||||
|
return next;
|
||||||
|
});
|
||||||
|
}, QUEUED_FEEDBACK_MS);
|
||||||
|
queuedFeedbackTimers.current.set(track.path, feedbackTimer);
|
||||||
|
|
||||||
void enqueueTop(dbTrackToTrack(track));
|
void enqueueTop(dbTrackToTrack(track));
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1018,6 +1052,7 @@ function QuickSearchPanel({
|
|||||||
result={item.result}
|
result={item.result}
|
||||||
query={trimmedQuery}
|
query={trimmedQuery}
|
||||||
active={item.result.kind === 'track' && item.result.track.path === currentPath}
|
active={item.result.kind === 'track' && item.result.track.path === currentPath}
|
||||||
|
queued={item.result.kind === 'track' && queuedTrackPaths.has(item.result.track.path)}
|
||||||
onPress={() => executeResult(item.result)}
|
onPress={() => executeResult(item.result)}
|
||||||
onQueueTrack={queueTrack}
|
onQueueTrack={queueTrack}
|
||||||
/>
|
/>
|
||||||
|
|||||||
Reference in New Issue
Block a user