mirror of
https://github.com/tapframe/NuvioStreaming.git
synced 2026-04-21 16:51:57 +00:00
ksplayer word splitting fix
This commit is contained in:
parent
0ab85ec870
commit
ecaaaa66ed
3 changed files with 289 additions and 291 deletions
|
|
@ -328,7 +328,7 @@ const KSPlayerCore: React.FC = () => {
|
|||
id: id || 'placeholder',
|
||||
type: type || 'movie'
|
||||
});
|
||||
const { metadata, loading: metadataLoading, groupedEpisodes: metadataGroupedEpisodes, cast, loadCast } = shouldLoadMetadata ? (metadataResult as any) : { metadata: null, loading: false, groupedEpisodes: {}, cast: [], loadCast: () => {} };
|
||||
const { metadata, loading: metadataLoading, groupedEpisodes: metadataGroupedEpisodes, cast, loadCast } = shouldLoadMetadata ? (metadataResult as any) : { metadata: null, loading: false, groupedEpisodes: {}, cast: [], loadCast: () => { } };
|
||||
const { settings } = useSettings();
|
||||
|
||||
// Logo animation values
|
||||
|
|
@ -559,7 +559,7 @@ const KSPlayerCore: React.FC = () => {
|
|||
useEffect(() => {
|
||||
return () => {
|
||||
if (isSpeedBoosted) {
|
||||
try { setPlaybackSpeed(originalSpeed); } catch {}
|
||||
try { setPlaybackSpeed(originalSpeed); } catch { }
|
||||
}
|
||||
};
|
||||
}, [isSpeedBoosted, originalSpeed]);
|
||||
|
|
@ -648,7 +648,7 @@ const KSPlayerCore: React.FC = () => {
|
|||
if (isOpeningAnimationComplete) {
|
||||
enableImmersiveMode();
|
||||
}
|
||||
return () => {};
|
||||
return () => { };
|
||||
}, [isOpeningAnimationComplete])
|
||||
);
|
||||
|
||||
|
|
@ -1203,7 +1203,7 @@ const KSPlayerCore: React.FC = () => {
|
|||
// Auto-select English audio track if available, otherwise first track
|
||||
if (selectedAudioTrack === null && formattedAudioTracks.length > 0) {
|
||||
// Look for English track first
|
||||
const englishTrack = formattedAudioTracks.find((track: {id: number, name: string, language?: string}) => {
|
||||
const englishTrack = formattedAudioTracks.find((track: { id: number, name: string, language?: string }) => {
|
||||
const lang = (track.language || '').toLowerCase();
|
||||
return lang === 'english' || lang === 'en' || lang === 'eng' ||
|
||||
(track.name && track.name.toLowerCase().includes('english'));
|
||||
|
|
@ -1393,9 +1393,9 @@ const KSPlayerCore: React.FC = () => {
|
|||
const isTablet = (Platform as any).isPad === true || Math.min(dw, dh) >= 768;
|
||||
setTimeout(() => {
|
||||
if (isTablet) {
|
||||
ScreenOrientation.unlockAsync().catch(() => {});
|
||||
ScreenOrientation.unlockAsync().catch(() => { });
|
||||
} else {
|
||||
ScreenOrientation.lockAsync(ScreenOrientation.OrientationLock.PORTRAIT_UP).catch(() => {});
|
||||
ScreenOrientation.lockAsync(ScreenOrientation.OrientationLock.PORTRAIT_UP).catch(() => { });
|
||||
}
|
||||
}, 50);
|
||||
}
|
||||
|
|
@ -1757,9 +1757,9 @@ const KSPlayerCore: React.FC = () => {
|
|||
try {
|
||||
const merged = { ...(saved || {}), subtitleSize: migrated };
|
||||
await storageService.saveSubtitleSettings(merged);
|
||||
} catch {}
|
||||
} catch { }
|
||||
}
|
||||
try { await mmkvStorage.removeItem(SUBTITLE_SIZE_KEY); } catch {}
|
||||
try { await mmkvStorage.removeItem(SUBTITLE_SIZE_KEY); } catch { }
|
||||
return;
|
||||
}
|
||||
// If no saved settings, use responsive default
|
||||
|
|
@ -2196,33 +2196,28 @@ const KSPlayerCore: React.FC = () => {
|
|||
|
||||
// Extract formatted segments from current cue
|
||||
if (currentCue?.formattedSegments) {
|
||||
// Split by newlines to get per-line segments
|
||||
const lines = (currentCue.text || '').split(/\r?\n/);
|
||||
const segmentsPerLine: SubtitleSegment[][] = [];
|
||||
let segmentIndex = 0;
|
||||
let currentLine: SubtitleSegment[] = [];
|
||||
|
||||
for (const line of lines) {
|
||||
const lineSegments: SubtitleSegment[] = [];
|
||||
const words = line.split(/(\s+)/);
|
||||
currentCue.formattedSegments.forEach(seg => {
|
||||
const parts = seg.text.split(/\r?\n/);
|
||||
parts.forEach((part, index) => {
|
||||
if (index > 0) {
|
||||
// New line found
|
||||
segmentsPerLine.push(currentLine);
|
||||
currentLine = [];
|
||||
}
|
||||
if (part.length > 0) {
|
||||
currentLine.push({ ...seg, text: part });
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
for (const word of words) {
|
||||
if (word.trim()) {
|
||||
if (segmentIndex < currentCue.formattedSegments.length) {
|
||||
lineSegments.push(currentCue.formattedSegments[segmentIndex]);
|
||||
segmentIndex++;
|
||||
} else {
|
||||
// Fallback if segment count doesn't match
|
||||
lineSegments.push({ text: word });
|
||||
}
|
||||
}
|
||||
if (currentLine.length > 0) {
|
||||
segmentsPerLine.push(currentLine);
|
||||
}
|
||||
|
||||
if (lineSegments.length > 0) {
|
||||
segmentsPerLine.push(lineSegments);
|
||||
}
|
||||
}
|
||||
|
||||
setCurrentFormattedSegments(segmentsPerLine.length > 0 ? segmentsPerLine : []);
|
||||
setCurrentFormattedSegments(segmentsPerLine);
|
||||
} else {
|
||||
setCurrentFormattedSegments([]);
|
||||
}
|
||||
|
|
@ -2248,9 +2243,9 @@ const KSPlayerCore: React.FC = () => {
|
|||
if (typeof saved.subtitleLineHeightMultiplier === 'number') setSubtitleLineHeightMultiplier(saved.subtitleLineHeightMultiplier);
|
||||
if (typeof saved.subtitleOffsetSec === 'number') setSubtitleOffsetSec(saved.subtitleOffsetSec);
|
||||
}
|
||||
} catch {} finally {
|
||||
} catch { } finally {
|
||||
// Mark subtitle settings as loaded so we can safely persist subsequent changes
|
||||
try { setSubtitleSettingsLoaded(true); } catch {}
|
||||
try { setSubtitleSettingsLoaded(true); } catch { }
|
||||
}
|
||||
})();
|
||||
}, []);
|
||||
|
|
@ -2725,7 +2720,7 @@ const KSPlayerCore: React.FC = () => {
|
|||
<LinearGradient
|
||||
start={{ x: 0, y: 0.5 }}
|
||||
end={{ x: 1, y: 0.5 }}
|
||||
colors={[ 'rgba(0,0,0,0.85)', 'rgba(0,0,0,0.0)' ]}
|
||||
colors={['rgba(0,0,0,0.85)', 'rgba(0,0,0,0.0)']}
|
||||
locations={[0, 1]}
|
||||
style={StyleSheet.absoluteFill}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -65,8 +65,17 @@ export const CustomSubtitles: React.FC<CustomSubtitlesProps> = ({
|
|||
}
|
||||
effectiveBottom = Math.max(0, effectiveBottom);
|
||||
|
||||
// Prepare content lines
|
||||
const lines = String(currentSubtitle).split(/\r?\n/);
|
||||
|
||||
// Detect RTL for each line
|
||||
const lineRTLStatus = lines.map(line => detectRTL(line));
|
||||
const hasRTL = lineRTLStatus.some(status => status);
|
||||
|
||||
// When using crisp outline, prefer SVG text with real stroke instead of blur shadow
|
||||
const useCrispSvgOutline = outline === true;
|
||||
// However, SVG text does not support complex text shaping (required for Arabic/RTL),
|
||||
// so we must fallback to standard Text component for RTL languages.
|
||||
const useCrispSvgOutline = outline === true && !hasRTL;
|
||||
|
||||
const shadowStyle = (textShadow && !useCrispSvgOutline)
|
||||
? {
|
||||
|
|
@ -76,12 +85,6 @@ export const CustomSubtitles: React.FC<CustomSubtitlesProps> = ({
|
|||
}
|
||||
: {};
|
||||
|
||||
// Prepare content lines
|
||||
const lines = String(currentSubtitle).split(/\r?\n/);
|
||||
|
||||
// Detect RTL for each line
|
||||
const lineRTLStatus = lines.map(line => detectRTL(line));
|
||||
|
||||
const displayFontSize = subtitleSize * inverseScale;
|
||||
const displayLineHeight = subtitleSize * lineHeightMultiplier * inverseScale;
|
||||
const svgHeight = lines.length * displayLineHeight;
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ export const safeDebugLog = (message: string, data?: any) => {
|
|||
};
|
||||
|
||||
// Add language code to name mapping
|
||||
export const languageMap: {[key: string]: string} = {
|
||||
export const languageMap: { [key: string]: string } = {
|
||||
'en': 'English',
|
||||
'eng': 'English',
|
||||
'es': 'Spanish',
|
||||
|
|
@ -189,7 +189,7 @@ export const detectRTL = (text: string): boolean => {
|
|||
// Arabic Presentation Forms-B: U+FE70–U+FEFF
|
||||
// Hebrew: U+0590–U+05FF
|
||||
// Persian/Urdu use Arabic script (no separate range)
|
||||
const rtlRegex = /[\u0590-\u05FF\u0600-\u06FF\u0750-\u077F\u08A0-\u08FF\uFB50-\uFDFF\uFE70-\uFEFF]/;
|
||||
const rtlRegex = /[\u0590-\u05FF\u0600-\u06FF\u0750-\u077F\u08A0-\u08FF\uFB50-\uFDFF\uFE70-\uFEFF]/g;
|
||||
|
||||
// Remove whitespace and count characters
|
||||
const nonWhitespace = text.replace(/\s/g, '');
|
||||
|
|
|
|||
Loading…
Reference in a new issue