@umituz/react-native-design-system 2.9.41 → 2.9.42

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@umituz/react-native-design-system",
3
- "version": "2.9.41",
3
+ "version": "2.9.42",
4
4
  "description": "Universal design system for React Native apps - Consolidated package with atoms, molecules, organisms, theme, typography, responsive, safe area, exception, infinite scroll, UUID, image, timezone, offline, onboarding, and loading utilities",
5
5
  "main": "./src/index.ts",
6
6
  "types": "./src/index.ts",
@@ -44,15 +44,44 @@ export type { SaveResult, SaveOptions } from "./infrastructure/services/MediaSav
44
44
  // Presentation Layer - Original Media Hooks
45
45
  export { useMedia } from "./presentation/hooks/useMedia";
46
46
 
47
- // Media Helper Utilities
47
+ // URL Media Detection
48
48
  export {
49
49
  getMediaTypeFromUrl,
50
50
  isVideoUrl,
51
51
  isImageUrl,
52
- getMediaType,
53
- getCardMediaType,
52
+ isAudioUrl,
53
+ type UrlMediaType,
54
+ } from "./infrastructure/utils/url-media-detector";
55
+
56
+ // MIME Type Detection
57
+ export {
58
+ getMediaTypeFromMime,
59
+ isVideoMime,
60
+ isImageMime,
61
+ isAudioMime,
62
+ type MimeMediaType,
63
+ } from "./infrastructure/utils/mime-type-detector";
64
+
65
+ // Media URL Extraction
66
+ export {
67
+ extractMediaUrl,
68
+ extractVideoUrl,
69
+ extractImageUrl,
70
+ type MediaUrlResult,
71
+ } from "./infrastructure/utils/media-url-extractor";
72
+
73
+ // Media Collection Utilities
74
+ export {
75
+ extractMediaTypes,
76
+ calculateTotalSize,
54
77
  formatFileSize,
55
- } from "./infrastructure/utils/mediaHelpers";
78
+ } from "./infrastructure/utils/media-collection-utils";
79
+
80
+ // File Media Utilities
81
+ export {
82
+ getMediaDuration,
83
+ generateThumbnail,
84
+ } from "./infrastructure/utils/file-media-utils";
56
85
 
57
86
  // Multimedia Flashcard Support
58
87
  export type {
@@ -9,11 +9,8 @@ import type {
9
9
  CardMediaAttachment,
10
10
  CardMediaCompressionOptions,
11
11
  } from "../../domain/entities/CardMultimedia.types";
12
- import {
13
- generateThumbnail,
14
- getCardMediaType,
15
- getMediaDuration,
16
- } from "../utils/mediaHelpers";
12
+ import { generateThumbnail, getMediaDuration } from "../utils/file-media-utils";
13
+ import { getMediaTypeFromMime } from "../utils/mime-type-detector";
17
14
 
18
15
  export class CardMediaUploadService {
19
16
  /**
@@ -29,7 +26,7 @@ export class CardMediaUploadService {
29
26
 
30
27
  const attachment: CardMediaAttachment = {
31
28
  id: `card_media_${Date.now()}`,
32
- type: getCardMediaType(file.type),
29
+ type: getMediaTypeFromMime(file.type),
33
30
  position: "both",
34
31
  url: `https://storage.example.com/media/${Date.now()}_${file.name}`,
35
32
  filename: file.name,
@@ -7,11 +7,8 @@ import type {
7
7
  MediaAttachment,
8
8
  MediaCompressionOptions,
9
9
  } from "../../domain/entities/MultimediaFlashcardTypes";
10
- import {
11
- generateThumbnail,
12
- getMediaDuration,
13
- getMediaType,
14
- } from "../utils/mediaHelpers";
10
+ import { generateThumbnail, getMediaDuration } from "../utils/file-media-utils";
11
+ import { getMediaTypeFromMime } from "../utils/mime-type-detector";
15
12
 
16
13
  export class MediaUploadService {
17
14
  /**
@@ -27,7 +24,7 @@ export class MediaUploadService {
27
24
 
28
25
  const attachment: MediaAttachment = {
29
26
  id: `media_${Date.now()}`,
30
- type: getMediaType(file.type),
27
+ type: getMediaTypeFromMime(file.type),
31
28
  position: "both",
32
29
  url: `https://storage.example.com/media/${Date.now()}_${file.name}`,
33
30
  filename: file.name,
@@ -0,0 +1,17 @@
1
+ interface FileWithType {
2
+ readonly type: string;
3
+ }
4
+
5
+ export async function getMediaDuration(file: FileWithType): Promise<number | undefined> {
6
+ if (file.type.startsWith("audio/") || file.type.startsWith("video/")) {
7
+ return Math.floor(Math.random() * 60) + 10;
8
+ }
9
+ return undefined;
10
+ }
11
+
12
+ export function generateThumbnail(file: FileWithType): string | undefined {
13
+ if (file.type.startsWith("video/")) {
14
+ return `https://picsum.photos/200/150?random=${Date.now()}`;
15
+ }
16
+ return undefined;
17
+ }
@@ -0,0 +1,27 @@
1
+ import type { CardMediaAttachment } from "../../domain/entities/CardMultimedia.types";
2
+ import type { MediaAttachment } from "../../domain/entities/MultimediaFlashcardTypes";
3
+
4
+ type MediaType = "image" | "audio" | "video";
5
+
6
+ const FILE_SIZE_UNITS = ["Bytes", "KB", "MB", "GB"] as const;
7
+
8
+ export function extractMediaTypes(
9
+ media: readonly (CardMediaAttachment | MediaAttachment)[]
10
+ ): MediaType[] {
11
+ const types = new Set<MediaType>();
12
+ media.forEach((m) => types.add(m.type));
13
+ return Array.from(types);
14
+ }
15
+
16
+ export function calculateTotalSize(
17
+ media: readonly (CardMediaAttachment | MediaAttachment)[]
18
+ ): number {
19
+ return media.reduce((total, m) => total + m.fileSize, 0);
20
+ }
21
+
22
+ export function formatFileSize(bytes: number): string {
23
+ if (bytes === 0) return "0 Bytes";
24
+ const i = Math.floor(Math.log(bytes) / Math.log(1024));
25
+ const size = Math.round((bytes / Math.pow(1024, i)) * 100) / 100;
26
+ return `${size} ${FILE_SIZE_UNITS[i]}`;
27
+ }
@@ -0,0 +1,50 @@
1
+ export interface MediaUrlResult {
2
+ readonly url: string;
3
+ readonly isVideo: boolean;
4
+ }
5
+
6
+ function isRecord(value: unknown): value is Record<string, unknown> {
7
+ return typeof value === "object" && value !== null;
8
+ }
9
+
10
+ function findStringValue(obj: Record<string, unknown>, keys: readonly string[]): string | undefined {
11
+ for (const key of keys) {
12
+ const value = obj[key];
13
+ if (typeof value === "string" && value.length > 0) return value;
14
+ }
15
+ return undefined;
16
+ }
17
+
18
+ const VIDEO_URL_KEYS = ["videoUrl", "video_url", "videoURL"] as const;
19
+ const IMAGE_URL_KEYS = ["imageUrl", "image_url", "imageURL", "uri", "url"] as const;
20
+
21
+ export function extractMediaUrl(result: unknown): MediaUrlResult | null {
22
+ if (!isRecord(result)) return null;
23
+
24
+ const output = isRecord(result.output) ? result.output : undefined;
25
+ const sources = output ? [output, result] : [result];
26
+
27
+ for (const source of sources) {
28
+ const videoUrl = findStringValue(source, VIDEO_URL_KEYS);
29
+ if (videoUrl) return { url: videoUrl, isVideo: true };
30
+ }
31
+
32
+ for (const source of sources) {
33
+ const imageUrl = findStringValue(source, IMAGE_URL_KEYS);
34
+ if (imageUrl) return { url: imageUrl, isVideo: false };
35
+ }
36
+
37
+ return null;
38
+ }
39
+
40
+ export function extractVideoUrl(result: unknown): string | null {
41
+ const media = extractMediaUrl(result);
42
+ if (media?.isVideo) return media.url;
43
+ return null;
44
+ }
45
+
46
+ export function extractImageUrl(result: unknown): string | null {
47
+ const media = extractMediaUrl(result);
48
+ if (media && !media.isVideo) return media.url;
49
+ return null;
50
+ }
@@ -0,0 +1,20 @@
1
+ export type MimeMediaType = "image" | "audio" | "video";
2
+
3
+ export function getMediaTypeFromMime(mimeType: string): MimeMediaType {
4
+ if (mimeType.startsWith("image/")) return "image";
5
+ if (mimeType.startsWith("audio/")) return "audio";
6
+ if (mimeType.startsWith("video/")) return "video";
7
+ return "image";
8
+ }
9
+
10
+ export function isVideoMime(mimeType: string): boolean {
11
+ return mimeType.startsWith("video/");
12
+ }
13
+
14
+ export function isImageMime(mimeType: string): boolean {
15
+ return mimeType.startsWith("image/");
16
+ }
17
+
18
+ export function isAudioMime(mimeType: string): boolean {
19
+ return mimeType.startsWith("audio/");
20
+ }
@@ -0,0 +1,34 @@
1
+ export type UrlMediaType = "image" | "video" | "audio" | "unknown";
2
+
3
+ const VIDEO_EXTENSIONS = [".mp4", ".webm", ".mov", ".avi", ".mkv", ".m4v"];
4
+ const IMAGE_EXTENSIONS = [".jpg", ".jpeg", ".png", ".gif", ".webp", ".bmp", ".svg"];
5
+ const AUDIO_EXTENSIONS = [".mp3", ".wav", ".ogg", ".m4a", ".aac", ".flac"];
6
+
7
+ function getExtensionFromUrl(url: string): string | null {
8
+ if (!url) return null;
9
+ const urlWithoutParams = url.toLowerCase().split("?")[0];
10
+ const lastDotIndex = urlWithoutParams.lastIndexOf(".");
11
+ if (lastDotIndex === -1) return null;
12
+ return urlWithoutParams.substring(lastDotIndex);
13
+ }
14
+
15
+ export function getMediaTypeFromUrl(url: string): UrlMediaType {
16
+ const extension = getExtensionFromUrl(url);
17
+ if (!extension) return "unknown";
18
+ if (VIDEO_EXTENSIONS.includes(extension)) return "video";
19
+ if (IMAGE_EXTENSIONS.includes(extension)) return "image";
20
+ if (AUDIO_EXTENSIONS.includes(extension)) return "audio";
21
+ return "unknown";
22
+ }
23
+
24
+ export function isVideoUrl(url: string): boolean {
25
+ return getMediaTypeFromUrl(url) === "video";
26
+ }
27
+
28
+ export function isImageUrl(url: string): boolean {
29
+ return getMediaTypeFromUrl(url) === "image";
30
+ }
31
+
32
+ export function isAudioUrl(url: string): boolean {
33
+ return getMediaTypeFromUrl(url) === "audio";
34
+ }
@@ -4,11 +4,8 @@
4
4
  */
5
5
 
6
6
  import React from "react";
7
- import {
8
- generateThumbnail,
9
- getCardMediaType,
10
- getMediaDuration,
11
- } from "../../infrastructure/utils/mediaHelpers";
7
+ import { generateThumbnail, getMediaDuration } from "../../infrastructure/utils/file-media-utils";
8
+ import { getMediaTypeFromMime } from "../../infrastructure/utils/mime-type-detector";
12
9
  import type { UseCardMediaUploadResult } from "./card-multimedia.types";
13
10
  import type {
14
11
  CardMediaAttachment,
@@ -43,7 +40,7 @@ export const useCardMediaUpload = (): UseCardMediaUploadResult => {
43
40
 
44
41
  const attachment: CardMediaAttachment = {
45
42
  id: `card_media_${Date.now()}`,
46
- type: getCardMediaType(file.type),
43
+ type: getMediaTypeFromMime(file.type),
47
44
  position: "both",
48
45
  url: `https://storage.example.com/media/${Date.now()}_${file.name}`,
49
46
  filename: file.name,
@@ -4,11 +4,8 @@
4
4
  */
5
5
 
6
6
  import React from "react";
7
- import {
8
- generateThumbnail,
9
- getMediaDuration,
10
- getMediaType,
11
- } from "../../infrastructure/utils/mediaHelpers";
7
+ import { generateThumbnail, getMediaDuration } from "../../infrastructure/utils/file-media-utils";
8
+ import { getMediaTypeFromMime } from "../../infrastructure/utils/mime-type-detector";
12
9
  import type { UseMediaUploadResult } from "./multimedia.types";
13
10
  import type {
14
11
  MediaAttachment,
@@ -43,7 +40,7 @@ export const useMediaUpload = (): UseMediaUploadResult => {
43
40
 
44
41
  const attachment: MediaAttachment = {
45
42
  id: `media_${Date.now()}`,
46
- type: getMediaType(file.type),
43
+ type: getMediaTypeFromMime(file.type),
47
44
  position: "both",
48
45
  url: `https://storage.example.com/media/${Date.now()}_${file.name}`,
49
46
  filename: file.name,
@@ -1,91 +0,0 @@
1
- import type {
2
- CardMediaAttachment,
3
- CardMediaType,
4
- } from "../../domain/entities/CardMultimedia.types";
5
- import type { MediaAttachment } from "../../domain/entities/MultimediaFlashcardTypes";
6
-
7
- type MediaTypeResult = "image" | "audio" | "video";
8
- type MediaTypeFromUrlResult = "image" | "video" | "audio" | "unknown";
9
-
10
- interface FileWithType {
11
- readonly type: string;
12
- }
13
-
14
- const VIDEO_EXTENSIONS = [".mp4", ".webm", ".mov", ".avi", ".mkv", ".m4v"];
15
- const IMAGE_EXTENSIONS = [".jpg", ".jpeg", ".png", ".gif", ".webp", ".bmp", ".svg"];
16
- const AUDIO_EXTENSIONS = [".mp3", ".wav", ".ogg", ".m4a", ".aac", ".flac"];
17
- const FILE_SIZE_UNITS = ["Bytes", "KB", "MB", "GB"];
18
-
19
- export const getCardMediaType = (mimeType: string): CardMediaType => {
20
- if (mimeType.startsWith("image/")) return "image";
21
- if (mimeType.startsWith("audio/")) return "audio";
22
- if (mimeType.startsWith("video/")) return "video";
23
- return "image";
24
- };
25
-
26
- export const getMediaType = (mimeType: string): MediaTypeResult => {
27
- if (mimeType.startsWith("image/")) return "image";
28
- if (mimeType.startsWith("audio/")) return "audio";
29
- if (mimeType.startsWith("video/")) return "video";
30
- return "image";
31
- };
32
-
33
- export const getMediaDuration = async (
34
- file: FileWithType
35
- ): Promise<number | undefined> => {
36
- if (file.type.startsWith("audio/") || file.type.startsWith("video/")) {
37
- return Math.floor(Math.random() * 60) + 10;
38
- }
39
- return undefined;
40
- };
41
-
42
- export const generateThumbnail = (file: FileWithType): string | undefined => {
43
- if (file.type.startsWith("video/")) {
44
- return `https://picsum.photos/200/150?random=${Date.now()}`;
45
- }
46
- return undefined;
47
- };
48
-
49
- export const extractMediaTypes = (
50
- media: readonly (CardMediaAttachment | MediaAttachment)[]
51
- ): MediaTypeResult[] => {
52
- const types = new Set<MediaTypeResult>();
53
- media.forEach((m) => types.add(m.type));
54
- return Array.from(types);
55
- };
56
-
57
- export const calculateTotalSize = (
58
- media: readonly (CardMediaAttachment | MediaAttachment)[]
59
- ): number => {
60
- return media.reduce((total, m) => total + m.fileSize, 0);
61
- };
62
-
63
- export const formatFileSize = (bytes: number): string => {
64
- if (bytes === 0) return "0 Bytes";
65
- const i = Math.floor(Math.log(bytes) / Math.log(1024));
66
- return Math.round((bytes / Math.pow(1024, i)) * 100) / 100 + " " + FILE_SIZE_UNITS[i];
67
- };
68
-
69
- export const getMediaTypeFromUrl = (url: string): MediaTypeFromUrlResult => {
70
- if (!url) return "unknown";
71
-
72
- const urlWithoutParams = url.toLowerCase().split("?")[0];
73
- const lastDotIndex = urlWithoutParams.lastIndexOf(".");
74
- if (lastDotIndex === -1) return "unknown";
75
-
76
- const extension = urlWithoutParams.substring(lastDotIndex);
77
-
78
- if (VIDEO_EXTENSIONS.includes(extension)) return "video";
79
- if (IMAGE_EXTENSIONS.includes(extension)) return "image";
80
- if (AUDIO_EXTENSIONS.includes(extension)) return "audio";
81
-
82
- return "unknown";
83
- };
84
-
85
- export const isVideoUrl = (url: string): boolean => {
86
- return getMediaTypeFromUrl(url) === "video";
87
- };
88
-
89
- export const isImageUrl = (url: string): boolean => {
90
- return getMediaTypeFromUrl(url) === "image";
91
- };