mirror of
https://github.com/tapframe/NuvioStreaming.git
synced 2026-03-11 17:45:38 +00:00
Pluginscreen UI changes
This commit is contained in:
parent
9ae0a7010c
commit
bbbc22f30f
5 changed files with 87 additions and 35 deletions
|
|
@ -57,6 +57,8 @@ export interface AppSettings {
|
|||
excludedQualities: string[]; // Array of quality strings to exclude (e.g., ['2160p', '4K', '1080p', '720p'])
|
||||
// Playback behavior
|
||||
alwaysResume: boolean; // If true, resume automatically without prompt when progress < 85%
|
||||
// Downloads
|
||||
enableDownloads: boolean; // Show Downloads tab and enable saving streams
|
||||
// Theme settings
|
||||
themeId: string;
|
||||
customThemes: CustomThemeDef[];
|
||||
|
|
@ -105,6 +107,8 @@ export const DEFAULT_SETTINGS: AppSettings = {
|
|||
excludedQualities: [], // No qualities excluded by default
|
||||
// Playback behavior defaults
|
||||
alwaysResume: true,
|
||||
// Downloads
|
||||
enableDownloads: false,
|
||||
// Theme defaults
|
||||
themeId: 'default',
|
||||
customThemes: [],
|
||||
|
|
|
|||
|
|
@ -458,6 +458,9 @@ const WrappedScreen: React.FC<{Screen: React.ComponentType<any>}> = ({ Screen })
|
|||
// Tab Navigator
|
||||
const MainTabs = () => {
|
||||
const { currentTheme } = useTheme();
|
||||
const { settings } = require('../hooks/useSettings');
|
||||
const { useSettings: useSettingsHook } = require('../hooks/useSettings');
|
||||
const { settings: appSettings } = useSettingsHook();
|
||||
const [hasUpdateBadge, setHasUpdateBadge] = React.useState(false);
|
||||
React.useEffect(() => {
|
||||
if (Platform.OS !== 'android') return;
|
||||
|
|
@ -829,16 +832,18 @@ const MainTabs = () => {
|
|||
),
|
||||
}}
|
||||
/>
|
||||
<Tab.Screen
|
||||
name="Downloads"
|
||||
component={DownloadsScreen}
|
||||
options={{
|
||||
tabBarLabel: 'Downloads',
|
||||
tabBarIcon: ({ color, size, focused }) => (
|
||||
<MaterialCommunityIcons name={focused ? 'download' : 'download-outline'} size={size} color={color} />
|
||||
),
|
||||
}}
|
||||
/>
|
||||
{appSettings?.enableDownloads !== false && (
|
||||
<Tab.Screen
|
||||
name="Downloads"
|
||||
component={DownloadsScreen}
|
||||
options={{
|
||||
tabBarLabel: 'Downloads',
|
||||
tabBarIcon: ({ color, size, focused }) => (
|
||||
<MaterialCommunityIcons name={focused ? 'download' : 'download-outline'} size={size} color={color} />
|
||||
),
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
<Tab.Screen
|
||||
name="Settings"
|
||||
component={SettingsScreen}
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ const ANDROID_STATUSBAR_HEIGHT = StatusBar.currentHeight || 0;
|
|||
const createStyles = (colors: any) => StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
backgroundColor: colors.background,
|
||||
backgroundColor: colors.darkBackground,
|
||||
},
|
||||
header: {
|
||||
flexDirection: 'row',
|
||||
|
|
@ -63,7 +63,7 @@ const createStyles = (colors: any) => StyleSheet.create({
|
|||
headerTitle: {
|
||||
fontSize: 34,
|
||||
fontWeight: 'bold',
|
||||
color: colors.white,
|
||||
color: colors.text,
|
||||
paddingHorizontal: 16,
|
||||
marginBottom: 24,
|
||||
},
|
||||
|
|
@ -71,7 +71,7 @@ const createStyles = (colors: any) => StyleSheet.create({
|
|||
flex: 1,
|
||||
},
|
||||
section: {
|
||||
backgroundColor: colors.darkBackground,
|
||||
backgroundColor: colors.elevation1,
|
||||
marginBottom: 16,
|
||||
borderRadius: 12,
|
||||
padding: 16,
|
||||
|
|
@ -852,6 +852,7 @@ const PluginsScreen: React.FC = () => {
|
|||
const [showboxUiToken, setShowboxUiToken] = useState<string>('');
|
||||
const [showboxSavedToken, setShowboxSavedToken] = useState<string>('');
|
||||
const [showboxScraperId, setShowboxScraperId] = useState<string | null>(null);
|
||||
const [showboxTokenVisible, setShowboxTokenVisible] = useState<boolean>(false);
|
||||
|
||||
// Multiple repositories state
|
||||
const [repositories, setRepositories] = useState<RepositoryInfo[]>([]);
|
||||
|
|
@ -1084,10 +1085,12 @@ const PluginsScreen: React.FC = () => {
|
|||
const s = await localScraperService.getScraperSettings(sb.id);
|
||||
setShowboxUiToken(s.uiToken || '');
|
||||
setShowboxSavedToken(s.uiToken || '');
|
||||
setShowboxTokenVisible(false);
|
||||
} else {
|
||||
setShowboxScraperId(null);
|
||||
setShowboxUiToken('');
|
||||
setShowboxSavedToken('');
|
||||
setShowboxTokenVisible(false);
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error('[ScraperSettings] Failed to load scrapers:', error);
|
||||
|
|
@ -1630,17 +1633,25 @@ const PluginsScreen: React.FC = () => {
|
|||
{showboxScraperId && scraper.id === showboxScraperId && settings.enableLocalScrapers && (
|
||||
<View style={{ marginTop: 16, paddingTop: 16, borderTopWidth: 1, borderTopColor: colors.elevation3 }}>
|
||||
<Text style={[styles.settingTitle, { marginBottom: 8 }]}>ShowBox UI Token</Text>
|
||||
<TextInput
|
||||
style={[styles.textInput, { marginBottom: 12 }]}
|
||||
value={showboxUiToken}
|
||||
onChangeText={setShowboxUiToken}
|
||||
placeholder="Paste your ShowBox UI token"
|
||||
placeholderTextColor={colors.mediumGray}
|
||||
autoCapitalize="none"
|
||||
autoCorrect={false}
|
||||
multiline={true}
|
||||
numberOfLines={3}
|
||||
/>
|
||||
<View style={{ flexDirection: 'row', alignItems: 'center', marginBottom: 12 }}>
|
||||
<TextInput
|
||||
style={[styles.textInput, { flex: 1, marginBottom: 0 }]}
|
||||
value={showboxUiToken}
|
||||
onChangeText={setShowboxUiToken}
|
||||
placeholder="Paste your ShowBox UI token"
|
||||
placeholderTextColor={colors.mediumGray}
|
||||
autoCapitalize="none"
|
||||
autoCorrect={false}
|
||||
secureTextEntry={showboxSavedToken.length > 0 && !showboxTokenVisible}
|
||||
multiline={false}
|
||||
numberOfLines={1}
|
||||
/>
|
||||
{showboxSavedToken.length > 0 && (
|
||||
<TouchableOpacity onPress={() => setShowboxTokenVisible(v => !v)} accessibilityRole="button" accessibilityLabel={showboxTokenVisible ? 'Hide token' : 'Show token'} style={{ marginLeft: 10 }}>
|
||||
<Ionicons name={showboxTokenVisible ? 'eye-off' : 'eye'} size={18} color={colors.primary} />
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
</View>
|
||||
<View style={styles.buttonRow}>
|
||||
{showboxUiToken !== showboxSavedToken && (
|
||||
<TouchableOpacity
|
||||
|
|
|
|||
|
|
@ -278,6 +278,8 @@ const SettingsScreen: React.FC = () => {
|
|||
|
||||
// Tablet-specific state
|
||||
const [selectedCategory, setSelectedCategory] = useState('account');
|
||||
const [downloadsDevUnlocked, setDownloadsDevUnlocked] = useState(false);
|
||||
const [versionTapCount, setVersionTapCount] = useState(0);
|
||||
|
||||
// States for dynamic content
|
||||
const [addonCount, setAddonCount] = useState<number>(0);
|
||||
|
|
@ -613,6 +615,22 @@ const SettingsScreen: React.FC = () => {
|
|||
)}
|
||||
isTablet={isTablet}
|
||||
/>
|
||||
{downloadsDevUnlocked && (
|
||||
<SettingItem
|
||||
title="Enable Downloads"
|
||||
description="Show Downloads tab and enable saving streams"
|
||||
icon="download"
|
||||
renderControl={() => (
|
||||
<Switch
|
||||
value={settings?.enableDownloads ?? true}
|
||||
onValueChange={(value) => updateSetting('enableDownloads', value)}
|
||||
trackColor={{ false: 'rgba(255,255,255,0.2)', true: currentTheme.colors.primary }}
|
||||
thumbColor={settings?.enableDownloads ? '#fff' : '#f4f3f4'}
|
||||
/>
|
||||
)}
|
||||
isTablet={isTablet}
|
||||
/>
|
||||
)}
|
||||
<SettingItem
|
||||
title="Notifications"
|
||||
description="Episode reminders"
|
||||
|
|
@ -646,6 +664,16 @@ const SettingsScreen: React.FC = () => {
|
|||
title="Version"
|
||||
description={getDisplayedAppVersion()}
|
||||
icon="info-outline"
|
||||
onPress={() => {
|
||||
if (downloadsDevUnlocked) return;
|
||||
const next = versionTapCount + 1;
|
||||
setVersionTapCount(next);
|
||||
if (next >= 5) {
|
||||
setDownloadsDevUnlocked(true);
|
||||
setVersionTapCount(0);
|
||||
openAlert('Developer option unlocked', 'Downloads toggle is now visible in Playback settings.');
|
||||
}
|
||||
}}
|
||||
isLast={true}
|
||||
isTablet={isTablet}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -221,6 +221,8 @@ const StreamCard = memo(({ stream, onPress, index, isLoading, statusMessage, the
|
|||
parentPosterUrl?: string | null;
|
||||
providerName?: string;
|
||||
}) => {
|
||||
const { useSettings } = require('../hooks/useSettings');
|
||||
const { settings } = useSettings();
|
||||
const { startDownload } = useDownloads();
|
||||
|
||||
// Handle long press to copy stream URL to clipboard
|
||||
|
|
@ -398,17 +400,19 @@ const StreamCard = memo(({ stream, onPress, index, isLoading, statusMessage, the
|
|||
color={theme.colors.white}
|
||||
/>
|
||||
</View>
|
||||
<TouchableOpacity
|
||||
style={[styles.streamAction, { marginLeft: 8, backgroundColor: theme.colors.elevation2 }]}
|
||||
onPress={handleDownload}
|
||||
activeOpacity={0.7}
|
||||
>
|
||||
<MaterialIcons
|
||||
name="download"
|
||||
size={20}
|
||||
color={theme.colors.highEmphasis}
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
{settings?.enableDownloads !== false && (
|
||||
<TouchableOpacity
|
||||
style={[styles.streamAction, { marginLeft: 8, backgroundColor: theme.colors.elevation2 }]}
|
||||
onPress={handleDownload}
|
||||
activeOpacity={0.7}
|
||||
>
|
||||
<MaterialIcons
|
||||
name="download"
|
||||
size={20}
|
||||
color={theme.colors.highEmphasis}
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
</TouchableOpacity>
|
||||
);
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in a new issue