@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.
Files changed (47) hide show
  1. package/README.md +17 -3
  2. package/android/src/main/java/com/technotoil/image_videoeditor/FrameGrabberModule.kt +2 -6
  3. package/android/src/main/java/com/technotoil/image_videoeditor/MediaEditorModule.kt +103 -37
  4. package/android/src/main/java/com/technotoil/image_videoeditor/MediaLibraryModule.kt +51 -35
  5. package/android/src/main/java/com/technotoil/image_videoeditor/RNVideoPreviewManager.kt +98 -117
  6. package/ios/RNMediaEditor.m +38 -7
  7. package/ios/RNMediaLibrary.m +19 -15
  8. package/ios/RNVideoPreviewManager.m +2 -0
  9. package/lib/commonjs/components/Icon.js +31 -0
  10. package/lib/commonjs/components/Icon.js.map +1 -0
  11. package/lib/commonjs/components/VideoEditor.js +97 -32
  12. package/lib/commonjs/components/VideoEditor.js.map +1 -1
  13. package/lib/commonjs/icons.js +35 -0
  14. package/lib/commonjs/icons.js.map +1 -0
  15. package/lib/commonjs/screens/CropScreen.js +5 -3
  16. package/lib/commonjs/screens/CropScreen.js.map +1 -1
  17. package/lib/commonjs/screens/EditorScreen.js +269 -84
  18. package/lib/commonjs/screens/EditorScreen.js.map +1 -1
  19. package/lib/commonjs/screens/PickScreen.js +221 -129
  20. package/lib/commonjs/screens/PickScreen.js.map +1 -1
  21. package/lib/module/components/Icon.js +25 -0
  22. package/lib/module/components/Icon.js.map +1 -0
  23. package/lib/module/components/VideoEditor.js +98 -33
  24. package/lib/module/components/VideoEditor.js.map +1 -1
  25. package/lib/module/icons.js +31 -0
  26. package/lib/module/icons.js.map +1 -0
  27. package/lib/module/screens/CropScreen.js +5 -3
  28. package/lib/module/screens/CropScreen.js.map +1 -1
  29. package/lib/module/screens/EditorScreen.js +230 -45
  30. package/lib/module/screens/EditorScreen.js.map +1 -1
  31. package/lib/module/screens/PickScreen.js +216 -124
  32. package/lib/module/screens/PickScreen.js.map +1 -1
  33. package/lib/typescript/src/components/Icon.d.ts +11 -0
  34. package/lib/typescript/src/components/VideoEditor.d.ts +10 -2
  35. package/lib/typescript/src/icons.d.ts +28 -0
  36. package/lib/typescript/src/screens/CropScreen.d.ts +2 -1
  37. package/lib/typescript/src/screens/EditorScreen.d.ts +2 -1
  38. package/lib/typescript/src/screens/PickScreen.d.ts +4 -1
  39. package/lib/typescript/src/types.d.ts +1 -0
  40. package/package.json +4 -4
  41. package/src/components/Icon.tsx +19 -0
  42. package/src/components/VideoEditor.tsx +67 -11
  43. package/src/icons.ts +28 -0
  44. package/src/screens/CropScreen.tsx +8 -3
  45. package/src/screens/EditorScreen.tsx +228 -62
  46. package/src/screens/PickScreen.tsx +198 -120
  47. 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;
@@ -52,6 +52,7 @@ export type VideoTrimOptions = ImageEditOptions & {
52
52
  mute?: boolean;
53
53
  isImage?: boolean;
54
54
  musicUri?: string;
55
+ musicOffsetMs?: number;
55
56
  };
56
57
  export type FrameCaptureOptions = {
57
58
  timeMs: number;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@technotoil/image-video-editor",
3
- "version": "0.1.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
- const resolvedItems = await Promise.all(
108
- picked.map(item => ensureExported(item, false))
109
- );
110
- setItems(resolvedItems);
111
- setCurrent(resolvedItems[0]);
112
- setScreen('editor');
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,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",
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
- onSave(outUri, item.type === 'image' ? outUri : undefined, item.durationMs);
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 {