@technotoil/image-video-editor 0.1.1 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +17 -3
- package/android/src/main/java/com/technotoil/image_videoeditor/FrameGrabberModule.kt +2 -6
- package/android/src/main/java/com/technotoil/image_videoeditor/MediaEditorModule.kt +103 -37
- package/android/src/main/java/com/technotoil/image_videoeditor/MediaLibraryModule.kt +51 -35
- package/android/src/main/java/com/technotoil/image_videoeditor/RNVideoPreviewManager.kt +98 -117
- package/ios/RNMediaEditor.m +38 -7
- package/ios/RNMediaLibrary.m +19 -15
- package/ios/RNVideoPreviewManager.m +2 -0
- package/lib/commonjs/components/Icon.js +31 -0
- package/lib/commonjs/components/Icon.js.map +1 -0
- package/lib/commonjs/components/VideoEditor.js +97 -32
- package/lib/commonjs/components/VideoEditor.js.map +1 -1
- package/lib/commonjs/icons.js +35 -0
- package/lib/commonjs/icons.js.map +1 -0
- package/lib/commonjs/screens/CropScreen.js +5 -3
- package/lib/commonjs/screens/CropScreen.js.map +1 -1
- package/lib/commonjs/screens/EditorScreen.js +269 -84
- package/lib/commonjs/screens/EditorScreen.js.map +1 -1
- package/lib/commonjs/screens/PickScreen.js +221 -129
- package/lib/commonjs/screens/PickScreen.js.map +1 -1
- package/lib/module/components/Icon.js +25 -0
- package/lib/module/components/Icon.js.map +1 -0
- package/lib/module/components/VideoEditor.js +98 -33
- package/lib/module/components/VideoEditor.js.map +1 -1
- package/lib/module/icons.js +31 -0
- package/lib/module/icons.js.map +1 -0
- package/lib/module/screens/CropScreen.js +5 -3
- package/lib/module/screens/CropScreen.js.map +1 -1
- package/lib/module/screens/EditorScreen.js +230 -45
- package/lib/module/screens/EditorScreen.js.map +1 -1
- package/lib/module/screens/PickScreen.js +216 -124
- package/lib/module/screens/PickScreen.js.map +1 -1
- package/lib/typescript/src/components/Icon.d.ts +11 -0
- package/lib/typescript/src/components/VideoEditor.d.ts +10 -2
- package/lib/typescript/src/icons.d.ts +28 -0
- package/lib/typescript/src/screens/CropScreen.d.ts +2 -1
- package/lib/typescript/src/screens/EditorScreen.d.ts +2 -1
- package/lib/typescript/src/screens/PickScreen.d.ts +4 -1
- package/lib/typescript/src/types.d.ts +1 -0
- package/package.json +4 -4
- package/src/components/Icon.tsx +19 -0
- package/src/components/VideoEditor.tsx +67 -11
- package/src/icons.ts +28 -0
- package/src/screens/CropScreen.tsx +8 -3
- package/src/screens/EditorScreen.tsx +228 -62
- package/src/screens/PickScreen.tsx +198 -120
- package/src/types.ts +1 -0
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { ImageStyle, StyleProp } from 'react-native';
|
|
3
|
+
import { Base64Icons } from '../icons';
|
|
4
|
+
interface IconProps {
|
|
5
|
+
name: keyof typeof Base64Icons;
|
|
6
|
+
size: number;
|
|
7
|
+
color?: string;
|
|
8
|
+
style?: StyleProp<ImageStyle>;
|
|
9
|
+
}
|
|
10
|
+
export declare const Icon: ({ name, size, color, style }: IconProps) => React.JSX.Element;
|
|
11
|
+
export {};
|
|
@@ -2,7 +2,7 @@ import React from 'react';
|
|
|
2
2
|
import type { MediaItem, MusicTrack } from '../types';
|
|
3
3
|
export interface VideoEditorProps {
|
|
4
4
|
onClose?: () => void;
|
|
5
|
-
onFinishExport?: (editedMedia: Record<string, MediaItem>, paths: string[], editedArray: MediaItem[], cameraMode?: string) => void;
|
|
5
|
+
onFinishExport?: (editedMedia: Record<string, MediaItem>, paths: string[], editedArray: MediaItem[], cameraMode?: string, globalMusic?: MusicTrack) => void;
|
|
6
6
|
headerTitle?: string;
|
|
7
7
|
customCancelIcon?: React.ReactNode;
|
|
8
8
|
onCancelPress?: () => void;
|
|
@@ -17,5 +17,13 @@ export interface VideoEditorProps {
|
|
|
17
17
|
* '16:9' = Landscape, '9:16' = Portrait, 'free' = No restriction (default)
|
|
18
18
|
*/
|
|
19
19
|
aspectRatio?: '1:1' | '4:3' | '4:5' | '16:9' | '9:16' | 'free';
|
|
20
|
+
/**
|
|
21
|
+
* Maximum video duration allowed (in milliseconds).
|
|
22
|
+
*/
|
|
23
|
+
maxVideoDurationMs?: number;
|
|
24
|
+
/** Filter the media type that can be picked. Default: 'any' */
|
|
25
|
+
mediaType?: 'photo' | 'video' | 'any';
|
|
26
|
+
/** Control which tabs are shown in the picker. Default: ['GALLERY', 'PHOTO', 'VIDEO'] */
|
|
27
|
+
mediaTabs?: ('GALLERY' | 'PHOTO' | 'VIDEO')[];
|
|
20
28
|
}
|
|
21
|
-
export default function VideoEditor({ onClose, onFinishExport, headerTitle, customCancelIcon, onCancelPress, cameraModes, defaultCameraMode, musicList, maxSelection, aspectRatio, }: VideoEditorProps): React.JSX.Element;
|
|
29
|
+
export default function VideoEditor({ onClose, onFinishExport, headerTitle, customCancelIcon, onCancelPress, cameraModes, defaultCameraMode, musicList, maxSelection, aspectRatio, maxVideoDurationMs, mediaType, mediaTabs, }: VideoEditorProps): React.JSX.Element;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export declare const Base64Icons: {
|
|
2
|
+
play: string;
|
|
3
|
+
pause: string;
|
|
4
|
+
"arrow-undo": string;
|
|
5
|
+
"arrow-redo": string;
|
|
6
|
+
close: string;
|
|
7
|
+
text: string;
|
|
8
|
+
"musical-notes": string;
|
|
9
|
+
crop: string;
|
|
10
|
+
"crop-outline": string;
|
|
11
|
+
"color-palette": string;
|
|
12
|
+
images: string;
|
|
13
|
+
"settings-outline": string;
|
|
14
|
+
"volume-mute": string;
|
|
15
|
+
"volume-high": string;
|
|
16
|
+
cut: string;
|
|
17
|
+
"arrow-forward": string;
|
|
18
|
+
"close-circle": string;
|
|
19
|
+
trash: string;
|
|
20
|
+
"trash-outline": string;
|
|
21
|
+
checkmark: string;
|
|
22
|
+
"chevron-down": string;
|
|
23
|
+
"camera-reverse-outline": string;
|
|
24
|
+
"square-outline": string;
|
|
25
|
+
"expand-outline": string;
|
|
26
|
+
flash: string;
|
|
27
|
+
"flash-off": string;
|
|
28
|
+
};
|
|
@@ -5,6 +5,7 @@ interface CropScreenProps {
|
|
|
5
5
|
onBack: () => void;
|
|
6
6
|
onSave: (uri: string, thumb?: string, duration?: number) => void;
|
|
7
7
|
aspectRatio?: '1:1' | '4:3' | '4:5' | '16:9' | '9:16' | 'free';
|
|
8
|
+
maxVideoDurationMs?: number;
|
|
8
9
|
}
|
|
9
|
-
export declare function CropScreen({ item, onBack, onSave, aspectRatio }: CropScreenProps): React.JSX.Element;
|
|
10
|
+
export declare function CropScreen({ item, onBack, onSave, aspectRatio, maxVideoDurationMs }: CropScreenProps): React.JSX.Element;
|
|
10
11
|
export {};
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import type { MediaItem, MusicTrack } from '../types';
|
|
3
|
-
export declare function EditorScreen({ items, initialIndex, onBack, onSaved, onOpenCrop, musicList, }: {
|
|
3
|
+
export declare function EditorScreen({ items, initialIndex, onBack, onSaved, onOpenCrop, musicList, maxVideoDurationMs, }: {
|
|
4
4
|
items: MediaItem[];
|
|
5
5
|
initialIndex?: number;
|
|
6
6
|
onBack: () => void;
|
|
7
7
|
onSaved: (updatedItems: MediaItem[]) => void;
|
|
8
8
|
onOpenCrop: (item: MediaItem) => void;
|
|
9
9
|
musicList?: MusicTrack[];
|
|
10
|
+
maxVideoDurationMs?: number;
|
|
10
11
|
}): React.JSX.Element;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import type { MediaItem } from '../types';
|
|
3
|
-
export declare function PickScreen({ items, onPicked, onNext, headerTitle, customCancelIcon, onCancelPress, cameraModes, onCameraModeChange, defaultCameraMode, maxSelection, aspectRatio, }: {
|
|
3
|
+
export declare function PickScreen({ isActive, items, onPicked, onNext, headerTitle, customCancelIcon, onCancelPress, cameraModes, onCameraModeChange, defaultCameraMode, maxSelection, aspectRatio, mediaType, mediaTabs, }: {
|
|
4
4
|
items: MediaItem[];
|
|
5
5
|
onPicked: (items: MediaItem[]) => void;
|
|
6
6
|
onNext: (picked: MediaItem[]) => void;
|
|
@@ -12,4 +12,7 @@ export declare function PickScreen({ items, onPicked, onNext, headerTitle, custo
|
|
|
12
12
|
defaultCameraMode?: string;
|
|
13
13
|
maxSelection?: number;
|
|
14
14
|
aspectRatio?: '1:1' | '4:3' | '4:5' | '16:9' | '9:16' | 'free';
|
|
15
|
+
mediaType?: 'photo' | 'video' | 'any';
|
|
16
|
+
mediaTabs?: ('GALLERY' | 'PHOTO' | 'VIDEO')[];
|
|
17
|
+
isActive?: boolean;
|
|
15
18
|
}): React.JSX.Element;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@technotoil/image-video-editor",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "A high-performance React Native image and video editor featuring video trimming, filters, photo overlay frames, and camera/gallery integration.",
|
|
5
5
|
"main": "lib/commonjs/index.js",
|
|
6
6
|
"module": "lib/module/index.js",
|
|
@@ -67,7 +67,6 @@
|
|
|
67
67
|
"@babel/core": "^7.25.2",
|
|
68
68
|
"@react-native/babel-preset": "0.84.0",
|
|
69
69
|
"@types/react": "^19.2.0",
|
|
70
|
-
"@types/react-native-vector-icons": "^6.4.18",
|
|
71
70
|
"del-cli": "^6.0.0",
|
|
72
71
|
"eslint": "^9.35.0",
|
|
73
72
|
"react": "19.2.3",
|
|
@@ -75,7 +74,6 @@
|
|
|
75
74
|
"react-native-builder-bob": "^0.39.1",
|
|
76
75
|
"react-native-image-crop-picker": "^0.51.1",
|
|
77
76
|
"react-native-safe-area-context": "^5.5.2",
|
|
78
|
-
"react-native-vector-icons": "^10.3.0",
|
|
79
77
|
"react-native-video": "6.19.1",
|
|
80
78
|
"typescript": "^5.9.2"
|
|
81
79
|
},
|
|
@@ -84,7 +82,6 @@
|
|
|
84
82
|
"react-native": ">=0.70.0",
|
|
85
83
|
"react-native-image-crop-picker": "^0.51.1",
|
|
86
84
|
"react-native-safe-area-context": "^5.5.2",
|
|
87
|
-
"react-native-vector-icons": "^10.3.0",
|
|
88
85
|
"react-native-video": ">=6.0.0"
|
|
89
86
|
},
|
|
90
87
|
"workspaces": [
|
|
@@ -103,5 +100,8 @@
|
|
|
103
100
|
}
|
|
104
101
|
]
|
|
105
102
|
]
|
|
103
|
+
},
|
|
104
|
+
"dependencies": {
|
|
105
|
+
"react-native-fs": "^2.20.0"
|
|
106
106
|
}
|
|
107
107
|
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Image, ImageStyle, StyleProp } from 'react-native';
|
|
3
|
+
import { Base64Icons } from '../icons';
|
|
4
|
+
|
|
5
|
+
interface IconProps {
|
|
6
|
+
name: keyof typeof Base64Icons;
|
|
7
|
+
size: number;
|
|
8
|
+
color?: string;
|
|
9
|
+
style?: StyleProp<ImageStyle>;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export const Icon = ({ name, size, color, style }: IconProps) => {
|
|
13
|
+
return (
|
|
14
|
+
<Image
|
|
15
|
+
source={{ uri: Base64Icons[name] }}
|
|
16
|
+
style={[{ width: size, height: size, tintColor: color, resizeMode: 'contain' }, style]}
|
|
17
|
+
/>
|
|
18
|
+
);
|
|
19
|
+
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React, { useState } from 'react';
|
|
2
|
-
import { Alert, StatusBar, useColorScheme } from 'react-native';
|
|
2
|
+
import { Alert, StatusBar, useColorScheme, View, Text, ActivityIndicator } from 'react-native';
|
|
3
3
|
import { SafeAreaProvider, SafeAreaView } from 'react-native-safe-area-context';
|
|
4
4
|
import { PickScreen } from '../screens/PickScreen';
|
|
5
5
|
import { CropScreen } from '../screens/CropScreen';
|
|
@@ -7,6 +7,8 @@ import { EditorScreen } from '../screens/EditorScreen';
|
|
|
7
7
|
import { ExportScreen } from '../screens/ExportScreen';
|
|
8
8
|
import { exportAsset } from '../native/MediaLibrary';
|
|
9
9
|
import type { MediaItem, MusicTrack } from '../types';
|
|
10
|
+
import { Icon as Ionicons } from './Icon';
|
|
11
|
+
|
|
10
12
|
|
|
11
13
|
export interface VideoEditorProps {
|
|
12
14
|
onClose?: () => void;
|
|
@@ -14,7 +16,8 @@ export interface VideoEditorProps {
|
|
|
14
16
|
editedMedia: Record<string, MediaItem>,
|
|
15
17
|
paths: string[],
|
|
16
18
|
editedArray: MediaItem[],
|
|
17
|
-
cameraMode?: string
|
|
19
|
+
cameraMode?: string,
|
|
20
|
+
globalMusic?: MusicTrack
|
|
18
21
|
) => void;
|
|
19
22
|
headerTitle?: string;
|
|
20
23
|
customCancelIcon?: React.ReactNode;
|
|
@@ -30,6 +33,14 @@ export interface VideoEditorProps {
|
|
|
30
33
|
* '16:9' = Landscape, '9:16' = Portrait, 'free' = No restriction (default)
|
|
31
34
|
*/
|
|
32
35
|
aspectRatio?: '1:1' | '4:3' | '4:5' | '16:9' | '9:16' | 'free';
|
|
36
|
+
/**
|
|
37
|
+
* Maximum video duration allowed (in milliseconds).
|
|
38
|
+
*/
|
|
39
|
+
maxVideoDurationMs?: number;
|
|
40
|
+
/** Filter the media type that can be picked. Default: 'any' */
|
|
41
|
+
mediaType?: 'photo' | 'video' | 'any';
|
|
42
|
+
/** Control which tabs are shown in the picker. Default: ['GALLERY', 'PHOTO', 'VIDEO'] */
|
|
43
|
+
mediaTabs?: ('GALLERY' | 'PHOTO' | 'VIDEO')[];
|
|
33
44
|
}
|
|
34
45
|
|
|
35
46
|
export default function VideoEditor({
|
|
@@ -43,6 +54,9 @@ export default function VideoEditor({
|
|
|
43
54
|
musicList,
|
|
44
55
|
maxSelection = 1,
|
|
45
56
|
aspectRatio = 'free',
|
|
57
|
+
maxVideoDurationMs,
|
|
58
|
+
mediaType = 'any',
|
|
59
|
+
mediaTabs = ['GALLERY', 'PHOTO', 'VIDEO'],
|
|
46
60
|
}: VideoEditorProps) {
|
|
47
61
|
const clampedMax = Math.min(5, Math.max(1, maxSelection));
|
|
48
62
|
const isDarkMode = useColorScheme() === 'dark';
|
|
@@ -52,19 +66,31 @@ export default function VideoEditor({
|
|
|
52
66
|
const [editedMedia, setEditedMedia] = useState<Record<string, MediaItem>>({});
|
|
53
67
|
const [originals, setOriginals] = useState<Record<string, MediaItem>>({});
|
|
54
68
|
const [selectedCameraMode, setSelectedCameraMode] = useState<string>(defaultCameraMode || 'STORY');
|
|
69
|
+
const [processing, setProcessing] = useState(false);
|
|
70
|
+
const [exportCache, setExportCache] = useState<Record<string, string>>({});
|
|
55
71
|
|
|
56
72
|
const ensureExported = async (item: MediaItem, ignoreEdits = false): Promise<MediaItem> => {
|
|
73
|
+
console.log(`[ensureExported] Start for item: ${item.id}, uri: ${item.uri}`);
|
|
57
74
|
if (!ignoreEdits && editedMedia[item.id]) {
|
|
75
|
+
console.log(`[ensureExported] Found in editedMedia! Returning early.`);
|
|
58
76
|
return editedMedia[item.id];
|
|
59
77
|
}
|
|
78
|
+
if (exportCache[item.id]) {
|
|
79
|
+
console.log(`[ensureExported] Found in exportCache! Returning cached URI: ${exportCache[item.id]}`);
|
|
80
|
+
return { ...item, uri: exportCache[item.id] };
|
|
81
|
+
}
|
|
60
82
|
if (!item.uri.startsWith('ph://') && !item.uri.startsWith('content://')) {
|
|
83
|
+
console.log(`[ensureExported] URI is already local file, skipping native export.`);
|
|
61
84
|
return item;
|
|
62
85
|
}
|
|
63
86
|
try {
|
|
87
|
+
console.log(`[ensureExported] Calling native exportAsset...`);
|
|
64
88
|
const fileUri = await exportAsset(item.id);
|
|
89
|
+
console.log(`[ensureExported] Native export success! New URI: ${fileUri}`);
|
|
90
|
+
setExportCache(prev => ({ ...prev, [item.id]: fileUri }));
|
|
65
91
|
return { ...item, uri: fileUri };
|
|
66
92
|
} catch (err: any) {
|
|
67
|
-
console.error('ASSET EXPORT FROM LIBRARY FAILED:', err?.message ?? err);
|
|
93
|
+
console.error('[ensureExported] ASSET EXPORT FROM LIBRARY FAILED:', err?.message ?? err);
|
|
68
94
|
return item;
|
|
69
95
|
}
|
|
70
96
|
};
|
|
@@ -77,8 +103,9 @@ export default function VideoEditor({
|
|
|
77
103
|
backgroundColor="transparent"
|
|
78
104
|
translucent={true}
|
|
79
105
|
/>
|
|
80
|
-
{screen === 'pick'
|
|
106
|
+
<View style={{ flex: 1, display: screen === 'pick' ? 'flex' : 'none' }}>
|
|
81
107
|
<PickScreen
|
|
108
|
+
isActive={screen === 'pick'}
|
|
82
109
|
items={items}
|
|
83
110
|
headerTitle={headerTitle}
|
|
84
111
|
customCancelIcon={customCancelIcon}
|
|
@@ -90,6 +117,8 @@ export default function VideoEditor({
|
|
|
90
117
|
onCameraModeChange={(mode) => {
|
|
91
118
|
setSelectedCameraMode(mode);
|
|
92
119
|
}}
|
|
120
|
+
mediaType={mediaType}
|
|
121
|
+
mediaTabs={mediaTabs}
|
|
93
122
|
onPicked={(picked: MediaItem[]) => {
|
|
94
123
|
// Save originals for "Fresh Start" editing
|
|
95
124
|
const newOriginals = { ...originals };
|
|
@@ -101,22 +130,48 @@ export default function VideoEditor({
|
|
|
101
130
|
setItems(picked);
|
|
102
131
|
}}
|
|
103
132
|
onNext={async (picked) => {
|
|
133
|
+
console.log(`[onNext] Triggered with ${picked?.length} items`);
|
|
134
|
+
if (processing) {
|
|
135
|
+
console.log(`[onNext] Aborting, already processing!`);
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
104
138
|
if (!picked || picked.length === 0) {
|
|
139
|
+
console.log(`[onNext] Aborting, picked is empty!`);
|
|
105
140
|
return;
|
|
106
141
|
}
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
142
|
+
console.log(`[onNext] Setting processing=true`);
|
|
143
|
+
setProcessing(true);
|
|
144
|
+
|
|
145
|
+
try {
|
|
146
|
+
console.log(`[onNext] Starting Promise.all for ${picked.length} items`);
|
|
147
|
+
const resolvedItems = await Promise.all(
|
|
148
|
+
picked.map(item => ensureExported(item, false))
|
|
149
|
+
);
|
|
150
|
+
|
|
151
|
+
console.log(`[onNext] Promise.all completed! Updating state...`);
|
|
152
|
+
setItems(resolvedItems);
|
|
153
|
+
setCurrent(resolvedItems[0]);
|
|
154
|
+
setScreen('editor');
|
|
155
|
+
console.log(`[onNext] Screen set to editor`);
|
|
156
|
+
} catch (e) {
|
|
157
|
+
console.error(`[onNext] Promise.all threw an error!`, e);
|
|
158
|
+
} finally {
|
|
159
|
+
console.log(`[onNext] Finally block - setting processing=false`);
|
|
160
|
+
setProcessing(false);
|
|
161
|
+
}
|
|
113
162
|
}}
|
|
114
163
|
/>
|
|
115
|
-
|
|
164
|
+
{processing && (
|
|
165
|
+
<View style={{ position: 'absolute', top: 0, left: 0, right: 0, bottom: 0, backgroundColor: 'rgba(0,0,0,0.5)', justifyContent: 'center', alignItems: 'center' }}>
|
|
166
|
+
<ActivityIndicator size="large" color="#ffffff" />
|
|
167
|
+
</View>
|
|
168
|
+
)}
|
|
169
|
+
</View>
|
|
116
170
|
{screen === 'editor' && current && (
|
|
117
171
|
<EditorScreen
|
|
118
172
|
items={items}
|
|
119
173
|
initialIndex={Math.max(0, items.findIndex(it => it.id === current.id))}
|
|
174
|
+
maxVideoDurationMs={maxVideoDurationMs}
|
|
120
175
|
onBack={() => {
|
|
121
176
|
setEditedMedia({});
|
|
122
177
|
const restoredItems = items.map(item => originals[item.id] || item);
|
|
@@ -157,6 +212,7 @@ export default function VideoEditor({
|
|
|
157
212
|
<CropScreen
|
|
158
213
|
item={current}
|
|
159
214
|
aspectRatio={aspectRatio}
|
|
215
|
+
maxVideoDurationMs={maxVideoDurationMs}
|
|
160
216
|
onBack={() => setScreen('editor')}
|
|
161
217
|
onSave={(uri, thumbnailUri, durationMs) => {
|
|
162
218
|
const updated = {
|
package/src/icons.ts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export const Base64Icons = {
|
|
2
|
+
"play": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFoAAABaCAYAAAA4qEECAAAACXBIWXMAAAsTAAALEwEAmpwYAAACKklEQVR4nO3dTWpUQRSG4SsSRUjAiehQx2aSLEBX4dShWxB3EFGMGWYL2UL3BpJ57riFNoOEHgiZ3Bb7FeE2CGLIT1WdU6e+ZwV1PxrSb6eS7joREREREZGIgAfAR+AMuAD2gSfW5woH2ONfP4APwCPr84UxvpL/Zw68A+5bn7N6XE8PvLE+awtDr02AHeszV4mbWwFHwAvrs0cfem0ADoDH1s9QBe5uAbwHHlo/S/Sh12bAW+Ce9TO5RHrHwCvr52ph6L/foWxbP58b5LUEDoGnXeso43JM/a2uVZQ1bzbpsdE3l/TYmjaT9NhbNZH0+DGETnr8WYRMevyahUp6/DsJkfTUY1J10lOXn2PSP+tqQ50uq0t66javJumJoXef9MQyBXY7j4hn5TLpiWtwlfTEt3CR9LTjm2nS054T4LWGjpr0tG0JfP1zGV9Dl/FZQ5dxoaHL0NCFfNLQ+X8YfgE2NHQ+enuXmYIlMyV4ZvpQKTN9TJqZPvhv+nYqMfT65Wxeum6QmS7QZKYrYQXokmNmMf4SF79muojeQjKnhh+Dq2ROzXpdvCZzasYjT90mc2pGA/fukzm1wgPPq0nm1Aon82bXqswDL/WPUUaZk/ml9fO5kWHg4xDJnFrCgWehkjm1BAMvQiZzancYeAidzKndYuBfYzI/tz57VW448qSZZE7tmgOfNpfMqQHfrxi43WROTV+mUPbrQfbGV/a5vh5ERERERESkq89vtSzZq2YJ5psAAAAASUVORK5CYII=",
|
|
3
|
+
"pause": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFoAAABaCAYAAAA4qEECAAAACXBIWXMAAAsTAAALEwEAmpwYAAABv0lEQVR4nO3cPUoDYRhF4Vupe9AlGt2lP5VxKRL7I4EpbIKYfMLl+N4+8ByYmXRvMpvNZrPZbDabzWaz2Ww2OzngBngEXoFPTu8TeAEegOv/4lky4A545/fbH39r96x8cs6J+h53bfUs2/Z6Xrqd1bNs2zfw0j1bPcsGHBaEHayeZWPRIvXEGkaZJ9YwyjyxhlHmiTWMMk+sYZR5Yg2jzBNrGGWeWMMo88QaRpkn1jDKPLGGUeaJNYwyT6xhlHliDaPME2sYZZ5YwyjzxBpGmSfWMMo8sYZR5ok1jDJPrGGUeWINo8wTaxhlnljDKPPEGkaZJ9YwyjyxhlHmiTWMMk+sYZR5Yg2jzBNrGGWeWMMo88QaRpkn1jDKPLGGUeaJNYwyT6xhlHliDaPME2sYZZ5YwyjzxBpGmSfWMMo8sYZR5ok1jDJPrGGUeWINo8wTaxhlnljDKPPEGkaZJ9YwyjyxhlHmiTWMMk+sYZR5Unb+7MPqifWgH2WeZduu1F66e6tn2Y4HU7fDqefuDbiyev7ijPD+zKhbu2fptidpd/y+/fCHdACejq/nXz45bZ7ZbDabzWaz2Ww2m81mswj2BY0LdofAZHslAAAAAElFTkSuQmCC",
|
|
4
|
+
"arrow-undo": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFoAAABaCAYAAAA4qEECAAAACXBIWXMAAAsTAAALEwEAmpwYAAAC20lEQVR4nO3cz4vNURjH8YcMRTYUEVZSZM/NX0BC2IqVxWSBjZQpxD9ABkvJXzDJxs812zHKneykZpJfCz/nrdM9N7fJMN8zc+/znHOe1252n/l0Ot/zPd9zrohzzjnnnHPOuT+Aiz1/un6VDKCdo4qSA+0sVZQcaOepouRAO1MVJQfauaooOdDOVkXJgXa+KkoOtDNWUXKgnbOKkgPtrFWUHGjnraLkPvoGvAfawGPgFnAK2AkskZwZKvl/3gG3gT3ZlZ5RybNNACeAIbEu45J7vQGOiFWFlNzrAbBFLCmw5K4PwFGxouCigxlgRKwovOzgOrBULADOUbZRsaKCkX1BrCh8ZM8AB8WKwkf2NLBZrLCwqQQMAeuAXcDpuN/xYxHKvi+WWNwmBdYAl4DPCyz7sFhideMfWA/cWUDRk8AysWQ+D0jRy3YS+J5Y9nGxxvLHWWB/4tz90uQW679GtuhnCw/LFC2xyPIBGuBuQtE3xSr+MrLFgLgU/JTwpcbe9DFX2WIEcDlhVO8QyzB4bBdYm/BgHBbriCNbDAGeNCz6huQAY1crgDMNi36knTlLQKth0ZPambNE5/W8iSntzFkCVjQs+qt25izhRQ+GTx0D4g/DAQHONizal3cpgGdFvrBYUuwruDXAVZrbrp07K8AG4EvDkt+a3ia1CLiX9VGxQlcaXbu1s2cDOAD8pLlx7ezZoHPcIPX00jHt/OYBGxPn5K62uQM0BtfJVxJWF7Md0v5fzACWxw2iVnzYPU2ci2cbk1IBq2JZL4CP6JkCNkmJgG3x+JWFg+h7pUTAauAVNpyXUgEj2FD2Dh2dZZS2a2auv/Xx290v5Tm53OnCSNHhUtA+qQXwWqHksWKXcHMJlygHWHDb1D1CheXdRJ8LHg8bRNXvXQBbYxmLKXwZGTV7NUILsDLeM3kef0tjvj9eNR3n+Yex2GHzB8edc84555xzzjnnnHNOivcbBy3/Miepva4AAAAASUVORK5CYII=",
|
|
5
|
+
"arrow-redo": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFoAAABaCAYAAAA4qEECAAAACXBIWXMAAAsTAAALEwEAmpwYAAAC1klEQVR4nO3bvY+NQRTH8SGWhCgQLw0KKqG+gr9AUJBohVKwVAqb3Eu1HYl4bTb8D0LB6kUndjdZQYcEkdhmXXxlYm5yc0l2Z+7uzDnznM9fcJ7fMznPM2/OGWOMMcYYY4yRARgvXUMj8JeFnSloCztj0BZ2xqAt7IxBW9gZg7awMwZtYWcM2sLOGLSFnTFoCztj0PWEDawA9gHngbvAJPAG+ArMI0PHKQ73EHAf+IQOesIGRoDTwAw6yQ8bOAm8Rz+ZYQM7gSfURVbYwDHgC3UadxL4tw78pl6d0gGvBG5Rt07RkEPQN6hbW0q7qFlHQshHKu/JbSm/cH7KXKuOk2CJ/pO7wDNgFGgBW/xMcpnqVRmyn/EN43vo7Rsy1qwu5JEhp9UTfuQWqFtPyB5wJjHgn8DlgnXL//ANLHXOJPbiw4Vr1zGSvbCenOKcgNrlj+SesGgfa8IJoGIk97WNjwl/F1udACpGshf2+GK1nRBS6/qH77ORIf/I+Z+8ENHtol/YrY7x1AkifiT3AM8jgx51gogfyT3Au8igW6VrVgn4HBn05tI1q5Rwgmh16ZpVsqAzsdaRCfA2MuhWrtqqEk58xrhYumaVEiYsk6VrVilhCt4FNpauWx1gL/Gulq5bnbBM+iEy6DlgW+na1QHuJYzqB6XrVgc4SJoLpWvX2D6mE4Lu+uNjpetXJdxHUXfcQJ1wgCZ2ybTfQ/tALhJwguHMAdeATaWfRTzgMcPrhp2bS8B+v2Nuq34DgB2FLwV9A16Gl7TO1Qw4KuQg+mtgt6sZMIYM08B6VzPgOjKMuZqF6283S6cMzLomCG2kZM/+BaxxTRBuasXuLy6V5gTtAduBR+TXjNYxCDiesKk7jCuuqYBVwClgaplDnqr+926xgAPAnYSdmoW8AnaVfj6RgD3AWeB2uNQ5Gz6i8xFT8BfhMuja0s9jjDHGGGOMMcYYY4wxxv3PH1MIAxrFORn0AAAAAElFTkSuQmCC",
|
|
6
|
+
"close": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFoAAABaCAYAAAA4qEECAAAACXBIWXMAAAsTAAALEwEAmpwYAAAB4UlEQVR4nO2cW2rDQBAE9RXn5FHOk49FF8rjFh0EChgcQmztzHbPdoEhX6GmsPXA8iyLMcYYY4wxxhhjjLkBwAXAK4DP47X/fVlEgII/gCcAb7hlA/C8kCPh/4ckn6yq/z8keWRV/e+QpIwt4f+AJFVsCf/j7NzwOG3k2VzG/7jsOUsbEbtD5B/WDNn9GrMHW+Zh5MTh4je+lEKnxe4ceed9SZBe0ZcWeRjpeLi45iXKN1q8RcRWcs36KHY/jCg4yg8CYrcyA4HQqQtMg4HIJQSGAUHgkMLIQTFL5JEDY7bIIwbHrJEzA2D2yBkh4Mhpt8At4H9yfeN9L0Hvvp7ovpOFYm9lIhPH3spFJoxdNzJR7PqRCWLPE3lg7PkiD4g9b+TE2I6cENuRr3HoBOBDRzzwyTAe+PIuHviGJR74FnyKyPVjgydy3djgi1wvNnHkOrH95WwCftwgAT9Ak4AfCUvADzkm4Md2E2AYFAQOoTANCCKXrjAOBkKnUzAPBGK3coNAwLHMz34h5Bq1r0P9R/dS+zqU10hI7evYhBejyOzraOKrfiT2dTQvr6q0zqyKv8SCvir+Eisnq/hLLFGt4i+xFriK/3E23y/9Po7XqvTNMsT9jTHGGGOMMcYYY5ZEvgGYmrPrcMYVcQAAAABJRU5ErkJggg==",
|
|
7
|
+
"text": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFoAAABaCAYAAAA4qEECAAAACXBIWXMAAAsTAAALEwEAmpwYAAABnUlEQVR4nO3czUrDQBhG4UDFfXuN/tyFVMS/y1RRUcSF7j0S60pqwdp5J5mc5wJmvhxCsvu6TpIkSZIkSV+AfeAaeKBd98BV/6w1Q/cDTMVVzdAtv8k/PdYMPSmdoTMMPeHQb8ABMC90/lr/vGsOHALvYwp9UPj8tXZ059GYQi9GHHoxmtClz691767OH9xA/FHpe3d1/jYDfTQa+mNooe/WzHPbQOi7ks+1zUDLNQOdNxB6WfK5thlo1g8APAMvwBmw10DoWcnnGhwqhZ4cDJ2BoTMwdAaGzsDQGRg6A0NnYOgMDJ2BoTMwdAaGzsDQGRg6A0NnYOgMDJ2BoTMwdAaGzsDQGRg6A0NnYOgMDJ2BoTMwdAaGzsDQGRg6A0NnYOgMDJ2BoTMwdAaGzsDQGRg6A0NnYOgMDF0eGxaUlF7IMinA8RahD2vPPbY3+XjTEqkN3r93Ik37zWa1NeD0l30YKf3dF61vK7hkOOrt3yiN1f6LoXjpWgW8MhxPXatYfRuHoulPx9537Jo/wxvgpP8x1+4hSZIkSZLUjdQnS6XqYMJdFmYAAAAASUVORK5CYII=",
|
|
8
|
+
"musical-notes": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFoAAABaCAYAAAA4qEECAAAACXBIWXMAAAsTAAALEwEAmpwYAAACjElEQVR4nO3dsYscZRzH4cEEPUWQgGAVhIgQO1PZ5A9QECubREgKC0shTRASuUKIdl4T7MRC0GssxEBIFz1FRGwEGwM5gmlCToUDTUQfWRiQwO25e7fzvu/efJ+/4P19GGaXd2fe7bqIiIiIiIioCw/hOZzFZXyPLXyD45WXt7zwFF7BO7iG30y3UXu9SwGP4STO4VPcNJ+/as/QJBzDGazhK/xpn2rP1AQcwmu4gt/3GzWhd4An8eUQcRO6h8P4eujICc0bJSInNBsJXQC2E7oABXVjJqHLUM6v3Zgp57NuzJTxC57txsxw/ui/Oq5Odvm6sbM4t/E5zve7fCu1Z2uKvdnud/TW+h2+p2vP0TyzX63reLO/Wh+uve6lY7rJvfUlHKm9xgPBFLXXdeBI6DIkdBkSugwJXYaELkNClyGhy5DQZUjoMiR0GRK6DAldhoQuQ0KXIaHLkNBlSOgyJHQZEroMCV2GhC5DQpchoYu99raj2ms7UPD2zpkTeiHwDD6cFjmh9wEncAHf4u/dIif0HPAIXsYHuPV/YRN6TjiK93F33rgJPQOs4L1FHPeQ0FNMnrjHj4sInNC7R95cZOSELngERBf/6d8pGUQXD1zN8x4gNav7tedrRv8iz1C2as/XDLw7YOjN2vM1A9cHDP1D7fmagRsDhv6k9nzNmJx/MWDo1drzNWNyBOWAoV+tPV8zcGegyPfwRO35xvBheLX2bE3BpYFCv157tqbg+YGO5FmpPdsYbh9nas/UJLwwy+9/M1qvPU/T8Jb928DjtWdpXn+20V59hEdrz7A0cLo/+2hW3+HF2ute5kcMTuFj/NT/i8Q//V90/IwvcHHyjEfttUZERERERHRj8i/lOUyIsyHgOAAAAABJRU5ErkJggg==",
|
|
9
|
+
"crop": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFoAAABaCAYAAAA4qEECAAAACXBIWXMAAAsTAAALEwEAmpwYAAAChklEQVR4nO2dvW4UMRRGTcMS/h8Aniq8TwAhKAgUUOUlQEqxygsAFYoQHSAQEhQUIIRookQ6aJQpQAo7nv35fMf+TrPFNt8cWR6vfX03JWOMMcYYY0wYgMulM1QLcB14CvzglO/AE+BaqgBgBuz2z/Ub2AO21CGuAm85mzfAlTR9yfMznm1PHeQhi3mQ6pPc8Usd5vOA6E+pPskdP9WBTgZEn6T6JHc8VocaJNUnuft+pg5WjWjgPLA/8DgHwIUS4aoQTWTJtYgmgmTgInAX+JDx4hslmumw2Tm5l/xq1ZRp2qI3/+LrRzINi55LVhf9dNGq6LlsCQccNSx6JpHc+ohOSoA7mwxNYNSit4CXmwpNYKSi/5J9G3jf0jo6RSNyaPJ+8YXK/F+ihmYFyRYtkmzRIskWvb5N+zCZs4kSmhFbnVEyjyJCaEbuJ0fIPJrSoVli07505qUoGZolT0YsWnT8ZNGiMz6LFh2kWrTotNqiRSUBFi2qu7BoUXGLRYsqiCxaVKZl0aJaOItOmoLD5kUjqupsWjTC0tlmRSOuT25SNAWKwJsTTaFK+6ZEU/A6QzOiKXxnpAnRBLiYU71oAkgemzkMuaEJInlM5lDkhCaQ5MmSKXoe7m51paIX4ZGcA6txYMmZWLIIS44/oqfGMfARuA9cKiF6qZtaE+dQ3t8P+EqbPFKLfk6bfFOLvkW7zJSiz62jecoE0Y7oXvbNBufqXbnoXvaNdVzQnwivi3YV7qeRbeAZ8KWypd9x37/kXtdrqpjkKUEGpTNWARatwaJFWLSIGlsxhySj+9m70hmrgOHuZzulM1YBi7ufvZD/I0XN8G/3s6P+c8eSjTHGGGOMMakV/gC1nBfq3SjpQQAAAABJRU5ErkJggg==",
|
|
10
|
+
"crop-outline": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFoAAABaCAYAAAA4qEECAAAACXBIWXMAAAsTAAALEwEAmpwYAAAChklEQVR4nO2dvW4UMRRGTcMS/h8Aniq8TwAhKAgUUOUlQEqxygsAFYoQHSAQEhQUIIRookQ6aJQpQAo7nv35fMf+TrPFNt8cWR6vfX03JWOMMcYYY0wYgMulM1QLcB14CvzglO/AE+BaqgBgBuz2z/Ub2AO21CGuAm85mzfAlTR9yfMznm1PHeQhi3mQ6pPc8Usd5vOA6E+pPskdP9WBTgZEn6T6JHc8VocaJNUnuft+pg5WjWjgPLA/8DgHwIUS4aoQTWTJtYgmgmTgInAX+JDx4hslmumw2Tm5l/xq1ZRp2qI3/+LrRzINi55LVhf9dNGq6LlsCQccNSx6JpHc+ohOSoA7mwxNYNSit4CXmwpNYKSi/5J9G3jf0jo6RSNyaPJ+8YXK/F+ihmYFyRYtkmzRIskWvb5N+zCZs4kSmhFbnVEyjyJCaEbuJ0fIPJrSoVli07505qUoGZolT0YsWnT8ZNGiMz6LFh2kWrTotNqiRSUBFi2qu7BoUXGLRYsqiCxaVKZl0aJaOItOmoLD5kUjqupsWjTC0tlmRSOuT25SNAWKwJsTTaFK+6ZEU/A6QzOiKXxnpAnRBLiYU71oAkgemzkMuaEJInlM5lDkhCaQ5MmSKXoe7m51paIX4ZGcA6txYMmZWLIIS44/oqfGMfARuA9cKiF6qZtaE+dQ3t8P+EqbPFKLfk6bfFOLvkW7zJSiz62jecoE0Y7oXvbNBufqXbnoXvaNdVzQnwivi3YV7qeRbeAZ8KWypd9x37/kXtdrqpjkKUEGpTNWARatwaJFWLSIGlsxhySj+9m70hmrgOHuZzulM1YBi7ufvZD/I0XN8G/3s6P+c8eSjTHGGGOMMakV/gC1nBfq3SjpQQAAAABJRU5ErkJggg==",
|
|
11
|
+
"color-palette": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFoAAABaCAYAAAA4qEECAAAACXBIWXMAAAsTAAALEwEAmpwYAAAFV0lEQVR4nO2dTWxVRRTHJxFbjYgJCBF1hyayASmIICBqjCs+3MgGXfi5MkFDdO2ydKGlRhISdAe6Aj82RhOWuiEQ0RAXFhf1K1pQ/MijQv2ZYw+Jbe67d+beM+/ed9/8kpcmzXtnzvt37syZmTOnziUSiUQikUgkEolEwg/gOuA+4FlgDHgfOAtMAheBGX1d1N+d1fcc0M9sEBuezQ0WwJ3AS8BHwCWq8xvwIbAPuMMNMsCNwFPAp8As8bgKfAI8CdzgBgVgsfa07+k9PwOvAbe4tgJcD7wCXKB+xIf94pNrE8A24Euax9fAo67fkTEReAv4p6IgHWAc2AjcpK/7gYPA5Yq2xbcJYNj1I8DdwGmqMwWsyWlnrb6nKqeAVa6fkMfRKEzr5Im8QOyqPftaWPiI6weAPbqgsGA8oF15/C2QP9gTrskALxjHxBsD2t5k2K58h+ddEwEe18WBJYsD43OMxd7jmoSMa0ZjZBWhl2CPDIGPuQZFF3kT3xXgCLAduBVYBmwFDnmM5ZZDx4yGmluApcBy4CHgbfUxb4Jc1YQ4+XTBkndzzudHgO9yPn8wwJc3c+xIG/fmfPYB9TUv9KsvztYe0o0reSJfQwTQMC4LGY7WOj8b3Z6OjqeNLQU9e8LVgQ4FeSu+IwG23sixM5UnlIqc91S8HuDHOzl25LtudTVsEH1FPtsD7K0vsHVZ4+RNGl3Ia7MOF0Xj/LoAPx4usCWHDItcr9BduCKWBdgbNtgPyUJsDgX4IRNkES+7XqC9adrDoaUBNof6SOjpkLCzNMCrnl/Sezxjbq8iFmsC/HjQ0+b+0gIGHD/95OnMoQC7Y8RjNMCPw542f4h6LKZnfL7IJDXiYXM18Bfx+FPa8JyQ/w6wu9dM2Axn5CA1hKKFwmrgPPGRtIR7cvxYVxAiZvFxzJSAMjtzHY2TRzS6GNIx+UDknpzVs0dlzFYfhrUXj+csmPKQDbSVMYSWvIvEfF6MIbQktyTmczxGmtavCxpJ8J8mdulnmguXyGa9pdDPdWkkAU9bCj1WY95FL6ji/6il0B80IO8iFlX9P2Ep9BcNybuwxsL/M5ZCf9ugvAtLLPw/X1rYjEamG5Z3YYWF/7+UFjajkZkG5l1YYOH/5dLCRhJ6Cc3DxP/SwmY0koYOuvtfWtiAydAq76IuTPwvLWxAeGeRd1EnJv5bCi33+GLlXdRNZf97uQSvknfRBCr5bym03EhNZHPJUui0Tdqdz603/iV9NRH7OEvvVifmcyYkE8pXaLlWnJgvsv2FfjEa4Y5Kv/EH8JkMF+Y9eYHYUiWgn+n8/yTFNRUtxdCvTIUkPNaKJjn+SP/R6RuRA5PQrZgFjgI7JP1KbxrIz53AsYAUNe+TlMYA3Nyjmhvf5CVIqi8jmsBoth3aKLSoSGyRlwdk6ReJHT9DPwb6CMcqdHK1qCd36dldhxHXgqoyMe6dHC3pz7utFDpiCsGOkr7sarPQw3p915LbSvpye2uFFuRCuvHO3lCFP3p7hRa0SkCZ6wlZrKywF5OJaxPAbqNNp50VCrO0X2hByuMYlPo5VrLt9wZGaEEKP1XMHJ31uZ+4oM0NrY2jPUr/VJkgJ4EVnm2tyEnwEX53bUajkVMVxR7x6MlFF0LPubajIddEhRXkrK74dmmcPKQ/d+uY7DMfHHaDAnPFqqSoSB30R2VGK4BFUlREErd7KPJJN6gwd+NpXw/y8WTP/C436DBXym2vVAmIcLouIm+r+zs2DuaOp+QI/4T+N4oqnEw92T/9TDbyn9GyD8c1WWVSe+pMRq7FOa0eM1gTXyKRSCQSiUQikUg4A/4FPhQA1U0118sAAAAASUVORK5CYII=",
|
|
12
|
+
"images": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFoAAABaCAYAAAA4qEECAAAACXBIWXMAAAsTAAALEwEAmpwYAAACjElEQVR4nO3cPW4TQRiH8ZX4CBIWLQUUnABSOdByC+5AoKBIGR8hH1eggnsEkJAAiZYqlDQoSITqQYsmlnF2xjPj17M72f9Pcue8nn0ymWxSbNOIiIiIiIiIiIiISAhwC3gJfAB+IRfaFu+BF8DWupHvA1/mo8Xnc9tqnZ2syGmx03e2Oy4kzW5O6PZMljTvckKfJX6IwFlOaMmg0IUodCEKHfYbOACmwG332gEOgXMSKLTfKfAw0OGRe08UhfbvZG/kpdhRO1uhux0k9DgigkJ3myb0eEwEhe42SegxocfQe4wn9J3eQrv3zajXtIqjY+G9tcY+TOhx3HvoimOft7duES22gT+DCF1x7NNQbBf5e+ywIqEr39lH7hyeuNcTd1xE7eTiod3X1n43kq1o6DHHbkqHHmvspo/QhrH3a/mm9RbaIPa+8Tft6oZeI9I8ci2xm1SbGEpapEuRa4g9iNAJ99lfgetNwFDv10Nr9l2I/dC0HfkWuNEEDHFnh9bruwj7ocONbXZXE1qr7wLsh+b9+L8BrhnM8ZkZzfkntE7f4u2Hdoi8uD2jOd7Ia86ZW7XOroXbD/WI+LH9ZjRn43c1Metc/jD7oQErdtIPozmLdzUbOY5i17n4QfZDVwhc3GujORs/jlLWefEh9kMjAK+W/gf8EbibMWdmdBwlxa4mdAt4ADwDnq76w2VAx1F9oSs+jsYb2vg4UugSx5FCF6LQhSh0IQpdiEIXotCFKHQhCl2IQhei0Fc9tFym0IUo9IBD68Eo6X7mhNajfgo96qd9npukeZ4Tess9YkzifAJuJodeeMCgYsdFvpcVeWln77bnj35B/qdtcdIeF9k7WURERERERERERKQZjb/rDdCaunHJHQAAAABJRU5ErkJggg==",
|
|
13
|
+
"settings-outline": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFoAAABaCAYAAAA4qEECAAAACXBIWXMAAAsTAAALEwEAmpwYAAAG+0lEQVR4nO2dWawURRSGSwUuIKDy4BZBDSoCvqhcLpsQEyNEYgJqwMRERCPgEmQJYtAnkUXZRF80KlwFXACDIEJMfFERiC/GGFGiCRdkETcUjQugn6nMGdM2UzXV3dXTPXP7eyJ3uqpOFT1VdU79p0apgoKCgoKCgoKCAEAn4EngEHAQWKT/FnymwAMysGEW+ai7oQF6Ade6vpXyFoc56Fi2CRgI9FbtBaAjsDYwWPuBFocyJjpWKTsUOBB4fg3QQTU6wOwKg7UX6Gwp02IZ6GZLuS7AvgplZqpGB3jXMGBzDM93Az60DLT+rJuh7KOGMltVowO0Gjp/EpgH9Af6AeOBxTK1VEM/sxSYIGUHAAukzkqsVI0OpQHMmttUo0PpbcuaK1SjA9ya9SgDY1W9IjuDqcAIyzPnA19kPcrA58B5FjuvB+4HBqs8IQtRkHVA19AzYwxOR1bovfVNIRu7AhtCzy1TecCyx/0SmA7cA2wmv2wC7gZmiM2VGJSHgZ5C4zMlDwM9ksZnuMoDMif75jDwKvAQMAq4DDhH4h4d5N99gBuBacBrKa0Br6u8IIuIj93EMeDZuHMicJreKQDLgZ887U66qDwhi4mPgb7Akz1nAg/KNyMu01TekJXbB62e7eomcY8TMWyZqPJGjC3c35a/N6dg38AY09smlSfEGYnCe8AQ4Ljh8516vk3Bzu7Axrp018WtjrLaryyfigBPW567IyV7TwdeiOhBGt1138bpLdVMYBuwSocZJe57S8Sv42rd0UC9eov2veHZb/SCllJ/9O7k+Qh275Zg2AAJ874sBxizqh2lRTUseMYXly2VzuokEGVinrdOnNruGWJTUtb4Mqi3B2P2AmdbOvypodzvwCVeOmKes7/y0L9ePozRkoAkHK/mgEhY0sS6xJ2wt91sWZRdudqHIU0yX8ZlmWM7b1rqGJm4I/a2lyTo3z5viilxa9tiGHHENGWEAS4F/jDU84meYlRKAD2Ab2NOiX5DqFp3ATxiOVmuxIyIbcy31DXZa4fc9CYmtJf5sE2L4sOgJxyN+UW/KTHc5YOWb8dZKS+MRx379nhadgQN0roLF1bErP9OS51L/ffof20/59i3K9O0I6pcYHgCZ2KXoc6/gL7+e/Vf28Mc+zYgLRuCxtzuYMiRJIsXpS2lKei0xW+PTnHPTZ5qkPFp2WA78a7EWg/tvGKpXwf1d+gF0rcYHVjv0L/FPts0LRgue+rZHtq6EPjVoa1dvg4LpN05Dm22mYSVPoJKWlawHTdGeWp3rmN7O3292Vrr4dimVrEOShxUCuWMROVyT52eTH0QP6fGkDPiyrmeBnoH9UX0nJqYb3KZJk8DfZT64nCcTibRSLTXgT5Qr1PHR9QXC+Muhotivtm+FsN7qQ/8JJjK9q65StJOkNGeBvqxHG/vPhAJg78zw1B0rVI6WRoOy0XAb46DXGuHZV8qDkvIEJ0pVQsXfE0VF3y7TC2+XfCwEL3mUcQoWVU/JAwqDQH+MdT9tt8enXJQ/KND/yakZUOcMOmwBBG0j3MeJr0qLRuCxmjhjAvPxKz/rgwD/66imn5p2hH1KOtY1KMnStHBQxkeZf3s2LcFadkR93A2UnI7sDDDw1l92OrKSckz9ytSF7mBPlqPyncR5AZ9gD/rTG6gc9CH+jKiyTHx3cRyx3Y2ZiigWZbQK0wuOwCuIRknqmWgAjdkKAlriZkNEKTZ15U8SWnTEl1D/TrD6rOMRI56yvjaQ/8u9mWQzUtz5Z1KcQHggYxku/o/eGtuZLuBoNIsEaK3ineo99PjRKTtytqQEL2neJG1FqJrp+jFiGlwY7WzJOL7l0RbPb1m9zPptIPQ5VDVaA2kVuicwixSK/RARVnsapNa4TG0WEaHW0dYdMk7UkwWeot6TBYqI7cE5Dn9rQXYE9HGzSpvAJPIZ0JnD+CpmFu4SSpvyMKQpxTl7pI2rb3TuETSd6eOXOTnM+l+cJw5WpSoOtS5IkKAyMaetHY+sQDewD9HpF79Vo6WrVVPOTTuKDmKfeWz6XKVRZIEexMbVB6Q3UOjMzLrcW4vV/1MzXqcy9sm2+VVk3J+eZXeV0+UW2x25/byKoM4fX14EQFuTqjn8432ZsdUWNTD680SlSfkzb7P4YLB3eT/gsHrZEr07jjVDEpBmawZpxodSluyrEk/fS1ryMcbnX5WVdZQuoHGdLI8XwQ6/SXNbqnjeWWbSNXKcfL+cum36cR+lWp0MJ9qzLUIK7Vy08T7JjfZIljcphodSlcGhdlv00hI9lOcH1PobJBJzGyPPw9yQIsaHcrE/XmQltD0s7pd/DxIGX1yLOL2zjX4wZtOIptIfiVPo0PlnJroOSMFkXJqih8lKygoKCgoKChQlfgXjY3V/aLhW7QAAAAASUVORK5CYII=",
|
|
14
|
+
"volume-mute": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFoAAABaCAYAAAA4qEECAAAACXBIWXMAAAsTAAALEwEAmpwYAAAClklEQVR4nO3bP2sUQRjH8SdR1KigWImdglj6DrTwz+uyshBJAlZBieALULAQsVAQLWwtxMLOSkQjUUn5lTETXY7kbu/mmXmO29+nv32e/TG3Ozs7ayYiIiIiIiIiIiIiIiIiIosPuBXdw0IDloA1gOheFhZwCHiQQlbQlQCHgUd7ISvoCoCjwJNuyAraGXACeDEasoJ2BJwG3u4XsoJ2ApwB3h0UsoJ2AJwF3o8LWUEXAs4DnyaFnBTWWQE2gF/AV+BOuuk638DvAt9yjVRrxeYBcAn4TE9WViud+KhnHmHnkNOxRm1YNOAy8KVvyEnh0+VP9lcU9piQk+1Zjzta5CZwH/iY/y5VWVmv22MOPVPYE0JOfnj85V/TmJX1/He9xCvsHiEnqyUNXwW2CGAFegbTK2zPY40bySEhJzM17RxQ9ZBzkVcEMgfAEeDphFLPgWOev52mwRsEMyezjMomIzkX+rcuHMUcTTM6m4zkTmNpChfKnE0xSuuP5E5TB034m7EKeo7W+iO501A4q6QgbN+QczPhrKIZwvYPOTcSziqbIuw6IecmwlllCjqrcmL/z0+Xjj3uJzWnN0NN7xpN7/TA0uiBJS3wh7KBPIJfJ5gNYVEpF3tJIBvCMmkudCG/qg9hhTyCahn2FeA7AWwor7I6hS5GvG2xsp7vBbycXS/puVvsWt6Y8qHFPNtm73MZ+B2w3SBlsmQD2kCzDOx4htwz7FRz2Qa2Jeyhd8g9wt60AW5yPJnD3sl/6bUKmxzX87FTjc1U0+YJcC5f58dyqlX1mpn3+cVel8fRRvSGgFPAGwXdAHBcHws1wu6N5bGCbgB90NkO+kS5HXanS6sKuhHgdnQPIiIiIiIiIiIiIiIiIiJii+EP8X2kOM0VOWAAAAAASUVORK5CYII=",
|
|
15
|
+
"volume-high": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFoAAABaCAYAAAA4qEECAAAACXBIWXMAAAsTAAALEwEAmpwYAAAFHklEQVR4nO2cW4xfUxSHV93GNapxKTOl4pIOmhLqEq0IwosHEeHdi7qWh0ZF0jRVprQpifAiqfAkKlVPUtKkDaIdHoxrlPBgxiBhNHqhxSc7PSP/TM9a5z5nn3P299istffav+7ZZ+3133uLBAKBQCAQCAQCgUAgEAgEpgXgGGAt8DMwBqxx/1Z3XK0COBLYyOGsqTu21gDMAF4invG642sNHFouVOqOrxUAKy2RqxIaOAK4F+iTtgM8mCRyhULfFzX/BXCVtBXgbuDfOoQG+oHdPV38DTwDHC1tArgNOJhG5IqEflPpaiswU9oAcBPwZ1qRyxYauCOhO7eUzJUmAywG9mYRuQKhX0jR5ThwiTQRYAHwW1aRyxY6iuVW4IeEbt3O9BxpEsAg8EsekasQOoppJrA5xTIyS5oAMDfF7Jl2oXtyaXOzBLznfb0FOBP4pojIVQrdE+c9wD9GCE+JrwCzgE+LilxUaOACYF4Ku6VGCC7PvkZ8AzgJ2FGGyEWEjpYG96f/F7AKODbBfsgIYxdwgviCGwyHEv/SKBDLkilNfQwMJFQRNxmhDIkPuC0s8FaZIucVOtpm/x7T3I/AQsPv1CiPjmMPcLrUSTQbNpQtsiNnPNbMdP8Blxm+Nxt1mHVSs8gvUhGSPZ6LonXZws3sc402XlP89rlsSuog4SNSmJwxXQi8m9D0sFaxc5lKlG3EsbKsj5lLdXZGa1LigKkYKZZ1rEooxz5p+L+i+OzKG9NkwwPASNYBUzFSTpFfE9vN2kFjVmssLDKTR/IMmIqREgAeN7p4w/Bzy0scz+YNZGneAVMxki7+81MsI28rXbjZviCjLt+niSuuwZ15B0zFSPosY7sleLQ0uqwhjucUnzOMOsicDBL/3+AfeQdMxUjyTP1gSo68KEeG9BNwlOLzpeJzV0aZ04lVxLcIKX/N7mXCFZOMHaOWtl2XMft4ohNCc/iv2b24ZWSG4rdF8Vmm2N+v2G/qitCbE1xvVPyWZck+gOsV++GuCH0W8Kix3X5Z8Vuk2I8o9vMV+9FOCD0JsFxx/Vr07CO1cNESFcduyUqRAVMxku4nszj2KfbHKfb7jc1cHAe6JnS/4rpHsT9esd+b0b5zQj+muIalIwsJH8Plxsdwg3FiKo7wMcyZ3t2QMb3bqNh3Pr3rNzYs2wy/dzJuWB7o9IYl5xZ8jlEkWjwdW/C2FJUmgGsN+6eVbsaNotJXis+dXS2TbgPOM+zcbN6fpZAPzC67TPpQ3gFTMVJe4X+LUfifr/g9rPh8lyauuAb7gE/yDJiKkRIAVhhdvG74faT4rC8SzIAltuFXKVKQKGuwfpydZ5zr1riiaFB90bW0D6d+IA2fSpFi155XJxw3UDMH4NUsO84uH6DZmtD0DiPTGDR+iVkhddDQI2Fj1u0rt24rfu6y02ypi4YdcpwALjV8bzGWm7VSNw05tjsGXG74neb1sd2GHEQfdhW/hL9K7VatPwfRpxTK3/foasWB6DWbpKsV2vbc8S1wovgGzbss9IgRgru3frX4Cs25/rYk4frbavEd/L/QuS6h++3eX+j0/IryKSkypM+dnTQJmnfpfhQ4W5oIfjwj8XyKLt1FooulyVD/wyi3J3T3WeOej/D4qR9te+5ucZ0sbYL6H6/q3Z4fjCqQ7Xq8ypPn2Nybd5OZxZXSdggPDE4fhCczvXgEdrTu+LryrPFQ3bG19aHu9cCv4aHuQCAQCAQCgUAgEAgEAgHxhv8AjorXLUvJuEsAAAAASUVORK5CYII=",
|
|
16
|
+
"cut": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFoAAABaCAYAAAA4qEECAAAACXBIWXMAAAsTAAALEwEAmpwYAAADwUlEQVR4nO2cu27UQBSGzQMExDUQCiRaqKADEvEUXITouLSkYUFC2i3TcGlRFHiHAA2UaaGDLAiJCApQErYgEUk2JHxolEFEwWN71z62Z+d8kqVI2R3/8+vs8cx4zkSRoiiKoiiKoiiKoiiKEgtwGLgJvADawLK92sBz4AYwXLVObwH2ARPAGumsA4+BQ1Xr9grgPLBI7ywCY1Xr9wLgqo3QfukCV6KaAJwE7gIvgbdAJ0X/R+BcGZGcx+TtZlcW2cAu4JJ9jvTDrKS4A32mCxcLJs+LCXb34zTwhnx8lRT4KOHGv4BJ85MChuw1CkwBGwnfeyAmOL4PJopXyM8tySGc+bnH8T0pZ7FluCvvdcsaiQD3gN8FmNySFGnGya5ITn0wAGMJkX1dTPi/+7cKMFjWZCvUTDzimOyhjSeONqaFtfthshX73nHzsz20Mepooy2o2x+TrWAzpY5jqIc2hhxtLNXc5KaEPpfopQKM3uNo46eAXv9MTkkdmWdIbD0Q4/gUdLrYIf6ZQ8xUD208dbQxU6BOf022HTBLnXGYIdtoxqn7pmTHvDfZdmI4YcLSSVq3YMvkjmQHB8LkbZ15mCBww46TzRBut73GbLrYlOzoQJlsAPbbhSBpWsGa/Bcbpa4UUiStDFrGy7pXJZhF+zqYDRwHPkveoy6RveC52a3IB4C99uXsKrJMpOg4ZiY9tZ7xFYFZTzZLnXZSM2vXRVaAOTMZqWFk+xHJvQI0ahTZ/kWyh2Y3oxCgWrPDMLlis8MyuezZnH1Ayryt9gVKimwlyhzZZgZ6GxixVyNmVjqYw7WSzW5k/DWo2TnTyBHHZp44NI3kiOqRmM8fTfi8ml1g6riT8h1NI30+DBspD0M1u4SxdBJhpxHKMTlssynX5DDNphqTwzKbak0Ow2zqYbL/ZjsqZ1ftq6XCXmUN7B6Ogitn89AMdtUvR+Vs7ugLJrILqJzNbcTAm203MZaxS6mZQctgphGBylkXYW9yFKqc3UnY23YFK2e3oxvRhStnDVpaUULl7EyBOv02W7hydq5grf6aLVw5uyqg18+hn3Dl7A8hzf6ZLVw52xbU7VcaEa6cnRbW7o/ZwpWz10rQ74fZgpWza3rUTzmVs/dFRf/fh4vm2IoCzB73qXJ23lR2iQl29+MU8Dqn9m++VM52xU9DTD9g8IKtIuuHdz5UznaBy1FNAE7Y/XyvgC8ZUssH4EzdK2fnq4xkL+mxcnbdHmt8sGrd3uKonF22f0/b/+m50YqiKIqiKIqiKIqiKJHf/AHJnmaYeQoYoQAAAABJRU5ErkJggg==",
|
|
17
|
+
"arrow-forward": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFoAAABaCAYAAAA4qEECAAAACXBIWXMAAAsTAAALEwEAmpwYAAABR0lEQVR4nO3cO0oFQQBE0dHAp+C6FUwMjIzcg4G4IUEw88MLr4gTiR+Qrhqfc88Kihv0TND0NEmSJEmSJOlXgCPgEngGHoAzYLP0rn+H98gf3Rh7IGAPePoktLFHAx6/CG3skYDzb0IbexRgM8c0dhpwAFz/EPsWOFx6687D2D0Yuwdj92DsHozdg7F7MHYPxu7B2D0Yuwdj92DsHozdg7F7MHYPxu7B2D0Yuwdj92DsHozdg7F7jF3kJZ2/F/u0uWnNx8j90hvXEvpu6Y1rOTpOlt650/BjmOfvXYGRCzByHkbOw8h5GDkPI+dh5DyMnIeR8zByHkbOw8h5GDkPI+dh5DyMnIeR8zByHkbOw8h5GDkPI+dh5Dy83NIBXBg5DNgHXozcCb01cgFwZeQC4HiOvZ2fOH57FNbIybekJ0mSJEmSpGm4V5HyL0XJeiP8AAAAAElFTkSuQmCC",
|
|
18
|
+
"close-circle": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFoAAABaCAYAAAA4qEECAAAACXBIWXMAAAsTAAALEwEAmpwYAAAEMklEQVR4nO2dS49URRTHKxFFgpElI5iAQb8A6kqJhPAICyIuxEQ0AV8bSBAImXHHjseKTOLXAMQFBD4AxkAQZuNG40J8MQ9ceW8y+DMnc0w6pHume/pU3ap7zy/pTef2uVX/3D5VderUuSE4juM4juM4juM4wwE8A7wJfApcBK4CD4CfgHmg1s+8fvdAr7mgv3lDbAx5u24BvAx8CXwL/M34PAauASeAzaHLAOuAj4FbwBPisQjcBD4Cng9dAXhBn7SHpOcv4CywIbQV4FngDDBH80gbTkubQpsAdgAz5MePwO5QOuITga+Bf8kXads0sDaUCLAV+I5yuAu8GkpC/o5G07TUyLRwVygB4D3gH8qlBj4IOQN8EXlOnArpw+chR4CDujhoC0+AQyEnxK8BFe2jBvaGHABeK3TgG2WA3Na0yGt1WtR27jQ6z9bFSFeYbnJZnfOKzxrp6zupRV4D3Kd7zCQNRGkUrqucTBlPnqW7zIoGKYSebLqnGXA6xfbTH4aLgUlgQj+Txoueqo99uacFv0XdFtM9Pism+9jfbyS22Njfx/4UdhyOKbRspFoxMeAe+8aM/slTe2CA7Y2G7b8eS+TNxkGjiWXutVqxB4qsdjcZB53sUxk078KSqRXuN6ob6esunrL5lXEfjscQWpJbLKmGEGZYsS1tjcKVGGlaC9hTL/dXH9KNWNhYLQum6WeaCxeLaoynsaknuZfXLYX+jLjUq3gqm3ySezlqKbRkdcamHkG4XEQWzlkK/Q1pqIZ0BU27izgDYuKQaLWSkBmJLNyzFPoX0lKv5Boadhe9/GwpdBMZoPUoYjcksvDIUmirqFcUsRsUWahc6AKFdteRyHX4YJhoMPTpXaLpnZzjS0FV4ILlsqXQvgRPtASXE6kxqQsOKh2xFNrDpIPZbim0B/5TBP61sXK22pKqBVtZdgNhT0PlWDEx8zoSbM5a5nUIx4I1ulVferrBRsP2Ly7Xh3HFlioBJSfQbMo+gUYbKqUYouV1ED8lzDKv48PYSY6/GzW0Vp/5kn6mIiQ5Pm3fKgr5MHrtj44nof/Pqagiq9DrJTRId5lNkoiuYktRka5yIonIPYeFfqB7zCSvWgO87cffEqGVW7rCpVS6DjqiLMd32873wHONCa1ib9OD6W1lAXgl5ACws/CqM4OQBc6ekBPAuy0sjPJ+yBEpj9OSUj+LkhMeckZL/pTsRqrsSvysUPrncaED385QEsAW4DblcKfxkj5jzrOnM19BStsuNT5PNlyu3yc/pE1vhTbBUiDqZCYh1ke62bwmtBWW4tnSyV8bEPhPLdT9YugKLJU8PgzciLzQEdvXZY+vU6Xn+6F7esflKJm+jWJc5tXWsWgpAaXDUvrZduAT4LxkA0kOsr4KZK7n9SBz+t09vUauPaq/9deDOI7jOI7jOI7jhCH5D9BzGCIG4NGgAAAAAElFTkSuQmCC",
|
|
19
|
+
"trash": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFoAAABaCAYAAAA4qEECAAAACXBIWXMAAAsTAAALEwEAmpwYAAABYElEQVR4nO3WTS5EURTE8WJAswWWiKVIfEWviBi1XTDSpMP0Ly95C2jR8Uq9+s3vvTmVm3OOVFVVVVVVVdsBFsAl8MrPvYxnF1s+N1/ANb93NXUd1oA9YL2DoN+Hu5QCOAbuxsJSrYFb4GjKoJfMx3KqkPeBL+bjc6i5QacGPcPWcT9JyGPQR8DNjjYFV2/jyjndMKyqqqr6e4SSG0LJDaHkhlByQyi5IZTcEEpuCCU3hJIbQskNoeSGUHJDKLkhlNwQSm4IJTeEkhtCyQ2h5IZQckMouSGU3BBKbgglN4SSG0LJDaHkhlByQyi5IZTcEEpuCCU3hJIbQskNoeSGUHJDKLkhlNwQSm4IJTeEkhtCyQ2h5IZQckMouSGU3BBKbgglN8CGPB9yAzyR51FugAvynMkNcAg8k2MFHMgRcBoS9go4kbPxZ58P/e2fDcgN8DC0C9ufXFVVVVVVVVUlD9+GFrvEn8LlcgAAAABJRU5ErkJggg==",
|
|
20
|
+
"trash-outline": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFoAAABaCAYAAAA4qEECAAAACXBIWXMAAAsTAAALEwEAmpwYAAABYElEQVR4nO3WTS5EURTE8WJAswWWiKVIfEWviBi1XTDSpMP0Ly95C2jR8Uq9+s3vvTmVm3OOVFVVVVVVVdsBFsAl8MrPvYxnF1s+N1/ANb93NXUd1oA9YL2DoN+Hu5QCOAbuxsJSrYFb4GjKoJfMx3KqkPeBL+bjc6i5QacGPcPWcT9JyGPQR8DNjjYFV2/jyjndMKyqqqr6e4SSG0LJDaHkhlByQyi5IZTcEEpuCCU3hJIbQskNoeSGUHJDKLkhlNwQSm4IJTeEkhtCyQ2h5IZQckMouSGU3BBKbgglN4SSG0LJDaHkhlByQyi5IZTcEEpuCCU3hJIbQskNoeSGUHJDKLkhlNwQSm4IJTeEkhtCyQ2h5IZQckMouSGU3BBKbgglN8CGPB9yAzyR51FugAvynMkNcAg8k2MFHMgRcBoS9go4kbPxZ58P/e2fDcgN8DC0C9ufXFVVVVVVVVUlD9+GFrvEn8LlcgAAAABJRU5ErkJggg==",
|
|
21
|
+
"checkmark": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFoAAABaCAYAAAA4qEECAAAACXBIWXMAAAsTAAALEwEAmpwYAAABaklEQVR4nO3ZsUoDQRRG4dXCaOFz24iFXTqfwSLsE9kJIhHLI4srCIImkflndud8EAikyL2HIQybYZAkSZIkSZIkSZIigA1wCzwDe2ALXGW+va/IO37a1p6th8iT19rz9RB58lJ7xh4iT+5qz9lD5OnzTe1ZFwu4AB7/iDwCl7VnXSwjBxg5wMgBRg4wcoCRA4wcYOQAIwcYOcDIAUYOMHKAkQOMHGDkACMHGDlg8ZGBc+BsaBhL/iMVuAYegHfgDbhvcVCWHHkyR256YFYQ+Xw+yc0OztIjfwu9b3UB1hD5y/yb3NwirClyqwvR4Eyru5vS0CyrXZAGZoiouSi9RK65ML1FrrE4vUZOBqD3yIkQGLl8EIxcPgxGLh8IIx/mP6Ew8nFOCYaRT3NMOIwce8K2W91TuLQDT+tvPMmB2KORy8cejVw+9mjk8rFHI5ePPRq5zNXvBniaX9N7r3CSJEmSJEmSJEkaPn0AMr2jP/wFTP0AAAAASUVORK5CYII=",
|
|
22
|
+
"chevron-down": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFoAAABaCAYAAAA4qEECAAAACXBIWXMAAAsTAAALEwEAmpwYAAABUUlEQVR4nO3av0oDQRRG8dHCqC8uiJDaQh/CIuwT2VgIUbE8MmgV8l/27szd84NAuv3uIULAlCJJkiRJkiRJkiRJkiRJagRwUV+RD7wBHoFP4A24BxYlKWABPADvwDfwBNxGPLhG3rTKGJvfyPW2Tc8Rfz4fWx6cLja7I1dfwOXYA9Y7Hp4mNvsjV+uIEcs9A7qPzeHI1bKVIV3GprXbgCvg5cCgAbgunaDVm5odlvGW5gdmuqGboRm2dze49Lm5u+F0tLXbA+hgY/eH0PC2NAfR4KZ0h9HQlrQH0sCGEFMeylwiT3kwc4s8xeHMNXJkgNlHjghh5IAgRg4Ig5HHD4SRj8M/Qhn5RJwRzMhn4oRwRo77d/8q488dQnHcp9VP8sSxByOPH9vIAbGNHBB7MPL4sQcjj/PV7w54/XvV936FkyRJkiRJkiRJkiRJkiSVYD+slS8141kMxgAAAABJRU5ErkJggg==",
|
|
23
|
+
"camera-reverse-outline": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFoAAABaCAYAAAA4qEECAAAACXBIWXMAAAsTAAALEwEAmpwYAAAEMElEQVR4nO2cy2tVRxjAjzGtjz4kvtCmK6GbFkRxU1xpRcGIVOmDQrtPbYzFB7iQtlfxERFBXfgvKC7FlbaFQltbXbRN4qbtpjXRCj5oVa5a6E8+OpLrNXPuPZMzM+fc8/3gbpKc+WZ+GeacmfN9N0kURVEURVEURVEURVGUXAEWAweBUaDO1Kmbtg4Ai2KPrxAAq4Gb+EPaXpVUGWAJcBf/3ANeS8oK8DxwGLjWNLBxYEh+3+L6rwjHl0lZMTLTGEq5dhXhKecSYmZuGuOW66YB3xAeiTktqQrAFuLRn1QB4KOcHuFckdgfJp0I8AqwAThHMfgPOAusl74lRQCYCXwK/Ggek5T/ERc/ANuAGVOV/Crwi2lYsfOzuJrKTFbJ2WRnn9lmuYjJA/M4JhuiTcAbQC/wAtAN9ACvA5uBmvnbh5H7POgiWtbkGAybf/J8hz7PBT42sysGF11EhziDaORXYGPmjto3RH3ACGH5x6WzITnS6lzEUbgsMTvNMhSEoos+73NrDCwDfgsxEJfOhWbAi+Wn1+/vfQ/CpWOhud98ZgxMB9YCJ4CvgRvAHeA28Jc5Zj0GrJO/bWNMLwGXqi4aM+NE7mzgcyOzXcbNNbNbjGsB8DsVFy2cBsZw5yrwbouxLfd1gyyT6LyQlxJdKePbhQeqKFo4ZZMNPGfelOdKVUUL+1LGuJEOFF0znxhnz5tTdpAjnST6i4Z2dxMeubnOsoxzsFNE1yZpO8bM3m4Z50Lg37KLfkZyRNnXU26MF/MKkmTFp+SIst9M3PJT2ibJSl5rchtxdhOO/ZY+fFBG0TWHWDXCcMESf0XZRLc9kyPN7NGUl9C5kGQlpOSAsm8lkwDMyStAkpW8AgMvW9q/hV+sCZY+l7SYohdb2r+Cf5xlu943YopeHjk3OujNOabo9yztS81KKIZCPQHFFH3Q0v5KwhJkAxVT9HeW9rvMtjgk3o8EYop+JO/pLDF2EB6vh1wxRQufpCRS/kF4hnztSmOLHrYlyADvEwcvLyJiixY2pMQ6SYdQBNEjkgtniSW5HGfoAIogWtiREk+eQg5Rcooiui4Jhy3ivgP8OcUEGknCqbRoTFbnghaxJSXss4wZS1ImvcdcOz1EQmPRRWMSDV9sow+ynKwBjkott9ng3DafMfOz48BbzUmOkjBpEicrLVq4LG+gM3cs2xgGCIxLJ0OVUyzzYnkiQUaS3IPh0slQ1E35Q7enr7mQso1gFFl043N2X14lFsDbocopyib6CVK61g/Mc+jzfMlICvT2pvSiG0/9pEhzb0NBZ49Jt51pijuXmoJOWR6+LUBBJ2WoM+wE/i5T5WyZcaqcla9HULKx1UX0jIg11WXkJ+fqX5MqpbLbk9zrJLlpZg+aHGK9QU5w1xxcbfVRx64oiqIoiqIoiqIoiqIoiqIoipJUnsc6JOcw0usCBgAAAABJRU5ErkJggg==",
|
|
24
|
+
"square-outline": "data:image/png;base64,eyJzdWNjZXNzIjpmYWxzZSwiZXJyb3IiOiJJY29uIHVuY2hlY2tlZC1jaGVja2JveCBpbiBpb3MtZ2x5cGhzIHN0eWxlcyBub3QgZm91bmQiLCJjb2RlIjoiUExBVEZPUk1fSUNPTl9OT1RfRk9VTkQifQ==",
|
|
25
|
+
"expand-outline": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFoAAABaCAYAAAA4qEECAAAACXBIWXMAAAsTAAALEwEAmpwYAAAC8klEQVR4nO2czW4TMRSFh9IQingykBBRxaK8S0GIPT9tUbIqvACo7aJkAc8DElXoJmXXD1m1UBWl07F9ndjD+aQsY59zZM0kvr5uGiGEEEIIIYQQQoj/GOA+8B74hR2/gQNgy1DnA+ADcG6o88x7N9PZZsBNlIuJoc5JRp1vrXS2GZhlNDAHNgw0bgAXGXWe2aTZbuIyo4F5JUFf2qTZbiIn40oeHVjpbDOQgxmwZ/wy3AL2/YvWHCudbQa6MnW/UJpKAO4BJzUGXU3YBIZcYtDFh01EyKUGXWzYsSE7ViHuJk5v0XYKDJtCcFo6ai4u6C6rY1rCyg7RWlzQoQaaNRGqscigY4yskhhtxQYdayg3sZqKDjrFWA5StBQfdKpBK1I1VBH0usPGYO5qgl5X2BjNWVXQqw7bcq7qgg74N3acsvnvN/1PrP6lrjPoZfu7s4DvDzuEPUrQt20VsoXfaHy1epG9wDGGt4T9KkHfa6uQrfymVC4mvr7nPuOYygjtYe8k6NuxCtnSbzTAHfdJHGPon8nX+QYMEsYcAN8XxjxO3Tm08LtWuHp5jdzjwq/GgcGYLuznfsyRRWVdCCGEEEIIIYQQQgghMsHVPu9j4AXwDNg0GHPTj7ULPGpqxqh7agh8Wdik/2pQnHUV7ut8Ntj4X+2eti/tHPiO1HPfkGNdytrOUJxNKWUl+w0GeLfExBvj4uxugr6XxsXZZL9RAD+XTPzD+LjBkwR9T42PGyT5jeYm9YYhH6UUQf3L9cgq7BS/ScROjI6EBZsInhgdcowyEDSxju1GEjKxDqIn0HXiEkLufWtFSSH3tlmoxJB71/5Wcsi9aeisIeRetCir6d4Y4piWsJL7co1EVSH37WKUokPuy1U/VYTcl8ur+nY36T+sdLYZyMnEUGe9Fwz6TfWczCu5MpOsHVrAXeBPRvHzSoK+yF4VBz5lNDCu5NFxaKWzzcBD4KPxyp5Vcjep83zoMrDSKYQQQgghhBBCCNFUyF/jytQRykBraQAAAABJRU5ErkJggg==",
|
|
26
|
+
"flash": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFoAAABaCAYAAAA4qEECAAAACXBIWXMAAAsTAAALEwEAmpwYAAACa0lEQVR4nO3bQWpUQRSF4SKDZOhcHQfcgJAlKG6hdQuJLiEiDYI6UASXoLgFISsQnYtOxEHEmU4Uf3nQE7Xfzet6VXWrb59v3HTXOYSGd1KdkoiIiIiMAA6AR8A34DOwBPbHXi+ZgCf8b5n7frIGcAj8XFP0l3Wvl0zAa0bkvqf8A7gO/FbRlQFvxkpW0YUAt6ySVXQBwB7wVkVXBty5qGQVPROwD3xQ0ZUB96aUrKJnAC4BX1V0ZcCDqSWr6EzAZeC7iq4MeLFJySq67HBk8j53qOHI4n3uUMORxfvsoYYji/fZQw1HFu/zhxqOLN4ZQg1HFu8MoYYji3eOUMORxTtHqOHI4p0l1HBk8c4SajiyeOcJNRxZvPOEGo4s3plCDUcW70yhhiOLd65Qw5HFO1eo4cjina234egd/Yh5iR24TZ/iXGKn0HBUSZxL7MBd+nWeIqDgcFTJsxQBBYejCn4AV9K2Kz0cVXCaIgCe0q/z4WstRdD5d/NJimL1UNCjj8MvcFMUqyevHi1SJKsHlWVnf9nDDLDn3U03qOeGd7auUMeZd67uUN7wz4Yj71y7UPRL70xdoqxfwDXvTLtQ9HPvPN2i7HB01TvPLhR96p2la5QRZzjqvOhj7xzdY75PoYajjoteeGfYCszzXsNRm6I1HE01o2QNR42K1nC0icySX230IZJyitZw1KhoDUc5NixZw1Gjou9nf9CuYzoNR42KPvE+61ZjGg1HjYpeeJ9z63ExDUeNir7pfcYQsGk4alT0kff5wmCchqOSWH/VV8NRo0vsj73PFQ5/X2IfHrMfhvvdtoiIiEgq6Q+nr/dgQAHSRwAAAABJRU5ErkJggg==",
|
|
27
|
+
"flash-off": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFoAAABaCAYAAAA4qEECAAAACXBIWXMAAAsTAAALEwEAmpwYAAAC/UlEQVR4nO3dPYoUQRTA8YeIGmmgiWgseIEFYzP1CuIZFg/ggiIDghq4iGcQE8HRSNYTzGouCCIGI2aaKP6l3dl1dGe6q7rrq1+9/wH640fRbRdvXBHLsizLsqziAo5KAQHHgfvAV+ATMAGOiYaALWDa3GQB1/KQw01ECfJ+r4ATGa/lAvBjBfRnUYScHRt4xppEGXI2bGAD+KUKunnxLZ7JbSV9ZgM7bRcjY615kwPPO7CTrGzgWsd1jBe6FGzgCDBTDV0CNnCjC1kFdE5s9s77vhroXNjATRdkVdCpsYFTwJcqoVNiA3ddkVVCp8AGzgLfqoeOjQ088UFWDR0Lm/UbR/VCx8CmZeOoauiQ2HRsHFUPHQobeN0HuSroodjA1b7I1UH3xcZx48igB2LjuHFk0MOwT7puHBl0+2jAtMPo41Dk6qE9Vvbgct9nNdhipcFenMaKjf3nBFZ87KVTWDGxDw5uxcX+7/BWLOx/DmzFw15xaKvnF2TodA2x7wdcBk5LWdg6hthXTBztAmdyf66rGmJfDthcurFZYSt7Lhpi9cRRSdjboiHWTxyV8Bj5DpyTsecwcbSbGfu2aAh45HCzuR4j8+axJhrymAadZcDeFC0tPgpcS/kY+VDCj1ODtfjy8inVyr4umlqswonnyo6N/baZI0krUXDEw76S9k4KjzjP7Ddp72IEsVdo7Etp72IE8bdQ2E/T3sFIIvwL8qWqf9KFisOFWNlZ/7+RImN1hh061mfYIaM9ww4V3Rl2Iugmwx4a7hl2Iugmw+4b/hl2ImjDTgjd/Lx5o+O4Lp/rL6r5XKdfThtHtrKX6oH8E7gojhl2f+jH4plhizd0M3F0vud56sbGrzsDz1UvNoknjqrFJsPEUZXYZJo4qg6bjBNHVWHT3buYE0fVYFPAxFEV2LS3k/A6XPZGpqX8nRrvSpo4cljZt2SsUdjEUQv2eJGb1oz6em0cJcAeN3LLEPsDydzSM3tLFA6xz4F7pfxue7QvPsuyLMuyRHe/AUjoq7FJeXprAAAAAElFTkSuQmCC"
|
|
28
|
+
};
|
|
@@ -100,8 +100,9 @@ interface CropScreenProps {
|
|
|
100
100
|
onBack: () => void;
|
|
101
101
|
onSave: (uri: string, thumb?: string, duration?: number) => void;
|
|
102
102
|
aspectRatio?: '1:1' | '4:3' | '4:5' | '16:9' | '9:16' | 'free';
|
|
103
|
+
maxVideoDurationMs?: number;
|
|
103
104
|
}
|
|
104
|
-
export function CropScreen({ item, onBack, onSave, aspectRatio = 'free' }: CropScreenProps) {
|
|
105
|
+
export function CropScreen({ item, onBack, onSave, aspectRatio = 'free', maxVideoDurationMs }: CropScreenProps) {
|
|
105
106
|
const isRatioLocked = aspectRatio !== 'free';
|
|
106
107
|
const getInitialRatioLabel = () => {
|
|
107
108
|
if (!aspectRatio || aspectRatio === 'free') return 'Free';
|
|
@@ -402,9 +403,13 @@ export function CropScreen({ item, onBack, onSave, aspectRatio = 'free' }: CropS
|
|
|
402
403
|
|
|
403
404
|
const outUri = item.type === 'image'
|
|
404
405
|
? await editImage(item.uri, options)
|
|
405
|
-
: await trimVideo(item.uri, { startMs: 0, endMs: item.durationMs || 10000, ...options });
|
|
406
|
+
: await trimVideo(item.uri, { startMs: 0, endMs: maxVideoDurationMs ? Math.min(item.durationMs || 10000, maxVideoDurationMs) : (item.durationMs || 10000), ...options });
|
|
406
407
|
|
|
407
|
-
|
|
408
|
+
const clampedDuration = item.type === 'video' && maxVideoDurationMs
|
|
409
|
+
? Math.min(item.durationMs || 10000, maxVideoDurationMs)
|
|
410
|
+
: item.durationMs;
|
|
411
|
+
|
|
412
|
+
onSave(outUri, item.type === 'image' ? outUri : undefined, clampedDuration);
|
|
408
413
|
} catch (err: any) {
|
|
409
414
|
Alert.alert('Apply failed', err?.message ?? 'Could not process crop.');
|
|
410
415
|
} finally {
|