@files-preview-app/preview-file 1.3.12 → 1.3.13

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/dist/angular.cjs CHANGED
@@ -249,6 +249,10 @@ var EXTENSION_MIME_MAP = {
249
249
  ".wav": "audio/wav",
250
250
  ".aac": "audio/aac",
251
251
  ".flac": "audio/flac",
252
+ ".m4a": "audio/mp4",
253
+ ".wma": "audio/x-ms-wma",
254
+ ".opus": "audio/opus",
255
+ ".weba": "audio/webm",
252
256
  // Code/Text
253
257
  ".txt": "text/plain",
254
258
  ".log": "text/plain",
@@ -575,6 +579,7 @@ var ICON_FULLSCREEN = `<svg width="24" height="24" viewBox="0 0 24 24" fill="non
575
579
  var ICON_COPY = `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path></svg>`;
576
580
  var ICON_FAST_FORWARD = `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="13 19 22 12 13 5 13 19"></polygon><polygon points="2 19 11 12 2 5 2 19"></polygon></svg>`;
577
581
  var ICON_REWIND = `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="11 19 2 12 11 5 11 19"></polygon><polygon points="22 19 13 12 22 5 22 19"></polygon></svg>`;
582
+ var ICON_SPEED = `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"></circle><polyline points="12 6 12 12 16 14"></polyline></svg>`;
578
583
  var ICON_EXTERNAL_WINDOW = `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="18" height="18" rx="2"></rect><line x1="3" y1="8" x2="21" y2="8"></line><circle cx="6" cy="5.5" r="0.75" fill="currentColor"></circle><circle cx="8.5" cy="5.5" r="0.75" fill="currentColor"></circle><polyline points="14 13 18 13 18 17"></polyline><line x1="11" y1="20" x2="18" y2="13"></line></svg>`;
579
584
  var ICON_RESET_ZOOM = `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"></circle><line x1="21" y1="21" x2="16.65" y2="16.65"></line><path d="M13 11a3 3 0 1 0-3 3"></path><path d="M10 11v3h3"></path></svg>`;
580
585
  var ICON_MAP = {
@@ -609,7 +614,8 @@ var ICON_MAP = {
609
614
  "openSeparateWindow": ICON_EXTERNAL_WINDOW,
610
615
  "reset-zoom": ICON_RESET_ZOOM,
611
616
  "zoom-reset": ICON_RESET_ZOOM,
612
- "resetZoom": ICON_RESET_ZOOM
617
+ "resetZoom": ICON_RESET_ZOOM,
618
+ "speed": ICON_SPEED
613
619
  };
614
620
  var ToolbarController = class {
615
621
  el;
@@ -2743,13 +2749,42 @@ var MediaPlugin = class {
2743
2749
  }
2744
2750
  });
2745
2751
  }
2752
+ actions.push({
2753
+ id: "open-window",
2754
+ icon: "open-window",
2755
+ label: "Open in Separate Full Window",
2756
+ type: "button",
2757
+ group: "actions",
2758
+ execute: () => {
2759
+ instance.openInSeparateWindow?.();
2760
+ }
2761
+ });
2746
2762
  return actions;
2747
2763
  }
2748
2764
  async render(ctx) {
2749
- const mimeType = ctx.metadata.mimeType || "application/octet-stream";
2750
- const isImage = mimeType.startsWith("image/") || IMAGE_EXTS.includes(ctx.metadata.extension || "");
2751
- const isVideo = mimeType.startsWith("video/") || VIDEO_EXTS.includes(ctx.metadata.extension || "");
2752
- const isAudio = mimeType.startsWith("audio/") || AUDIO_EXTS.includes(ctx.metadata.extension || "");
2765
+ const ext = (ctx.metadata.extension || "").toLowerCase();
2766
+ let mimeType = ctx.metadata.mimeType || "";
2767
+ if (!mimeType || mimeType === "application/octet-stream") {
2768
+ const audioMimes = {
2769
+ ".mp3": "audio/mpeg",
2770
+ ".wav": "audio/wav",
2771
+ ".ogg": "audio/ogg",
2772
+ ".flac": "audio/flac",
2773
+ ".aac": "audio/aac",
2774
+ ".m4a": "audio/mp4",
2775
+ ".wma": "audio/x-ms-wma",
2776
+ ".opus": "audio/opus",
2777
+ ".weba": "audio/webm"
2778
+ };
2779
+ if (audioMimes[ext]) {
2780
+ mimeType = audioMimes[ext];
2781
+ } else {
2782
+ mimeType = "application/octet-stream";
2783
+ }
2784
+ }
2785
+ const isImage = mimeType.startsWith("image/") || IMAGE_EXTS.includes(ext);
2786
+ const isVideo = mimeType.startsWith("video/") || VIDEO_EXTS.includes(ext);
2787
+ const isAudio = mimeType.startsWith("audio/") || AUDIO_EXTS.includes(ext);
2753
2788
  let url = "";
2754
2789
  let naturalW = 800;
2755
2790
  let naturalH = 600;
@@ -2821,10 +2856,79 @@ var MediaPlugin = class {
2821
2856
  video.addEventListener("canplay", onMeta, { once: true });
2822
2857
  }
2823
2858
  } else if (isAudio) {
2859
+ const audioCard = document.createElement("div");
2860
+ audioCard.className = "fp-audio-card";
2861
+ const artWrapper = document.createElement("div");
2862
+ artWrapper.className = "fp-audio-artwork-wrapper";
2863
+ const disc = document.createElement("div");
2864
+ disc.className = "fp-audio-disc";
2865
+ const discCenter = document.createElement("div");
2866
+ discCenter.className = "fp-audio-disc-center";
2867
+ const discHole = document.createElement("div");
2868
+ discHole.className = "fp-audio-disc-hole";
2869
+ discCenter.appendChild(discHole);
2870
+ disc.appendChild(discCenter);
2871
+ artWrapper.appendChild(disc);
2872
+ audioCard.appendChild(artWrapper);
2873
+ const info = document.createElement("div");
2874
+ info.className = "fp-audio-info";
2875
+ const title = document.createElement("div");
2876
+ title.className = "fp-audio-title";
2877
+ title.textContent = ctx.metadata.name || "Audio Track";
2878
+ const badges = document.createElement("div");
2879
+ badges.className = "fp-audio-badges";
2880
+ const extTag = document.createElement("span");
2881
+ extTag.className = "fp-audio-ext-tag";
2882
+ const cleanExt = (ext || ".mp3").replace(".", "").toUpperCase();
2883
+ extTag.textContent = `${cleanExt} AUDIO`;
2884
+ badges.appendChild(extTag);
2885
+ const timeTag = document.createElement("span");
2886
+ timeTag.className = "fp-audio-time-tag";
2887
+ timeTag.textContent = "0:00";
2888
+ badges.appendChild(timeTag);
2889
+ info.appendChild(title);
2890
+ info.appendChild(badges);
2891
+ audioCard.appendChild(info);
2892
+ const waveform = document.createElement("div");
2893
+ waveform.className = "fp-audio-waveform";
2894
+ for (let i = 0; i < 16; i++) {
2895
+ const bar = document.createElement("div");
2896
+ bar.className = "fp-audio-wave-bar";
2897
+ waveform.appendChild(bar);
2898
+ }
2899
+ audioCard.appendChild(waveform);
2900
+ const nativeWrapper = document.createElement("div");
2901
+ nativeWrapper.className = "fp-audio-native-wrapper";
2824
2902
  const audio = document.createElement("audio");
2825
2903
  audio.src = url;
2826
2904
  audio.controls = true;
2827
- element = audio;
2905
+ nativeWrapper.appendChild(audio);
2906
+ audioCard.appendChild(nativeWrapper);
2907
+ const onPlay = () => {
2908
+ disc.classList.add("playing");
2909
+ waveform.classList.add("playing");
2910
+ };
2911
+ const onPause = () => {
2912
+ disc.classList.remove("playing");
2913
+ waveform.classList.remove("playing");
2914
+ };
2915
+ const formatTime = (secs) => {
2916
+ if (!isFinite(secs) || isNaN(secs)) return "0:00";
2917
+ const m = Math.floor(secs / 60);
2918
+ const s = Math.floor(secs % 60);
2919
+ return `${m}:${s < 10 ? "0" : ""}${s}`;
2920
+ };
2921
+ const onTimeUpdate = () => {
2922
+ timeTag.textContent = `${formatTime(audio.currentTime)} / ${formatTime(audio.duration)}`;
2923
+ };
2924
+ const onLoadedMetadata = () => {
2925
+ timeTag.textContent = `0:00 / ${formatTime(audio.duration)}`;
2926
+ };
2927
+ audio.addEventListener("play", onPlay);
2928
+ audio.addEventListener("pause", onPause);
2929
+ audio.addEventListener("timeupdate", onTimeUpdate);
2930
+ audio.addEventListener("loadedmetadata", onLoadedMetadata);
2931
+ element = audioCard;
2828
2932
  mediaElement = audio;
2829
2933
  } else {
2830
2934
  element = document.createElement("div");
@@ -2834,11 +2938,12 @@ var MediaPlugin = class {
2834
2938
  scrollWrapper.className = "fp-media-scroll-wrapper";
2835
2939
  scrollWrapper.style.minWidth = "100%";
2836
2940
  scrollWrapper.style.minHeight = "100%";
2837
- scrollWrapper.style.width = "max-content";
2838
- scrollWrapper.style.height = "max-content";
2941
+ scrollWrapper.style.width = isAudio ? "100%" : "max-content";
2942
+ scrollWrapper.style.height = isAudio ? "100%" : "max-content";
2839
2943
  scrollWrapper.style.display = "flex";
2840
2944
  scrollWrapper.style.flexDirection = "column";
2841
2945
  scrollWrapper.style.alignItems = "center";
2946
+ scrollWrapper.style.justifyContent = isAudio ? "center" : "flex-start";
2842
2947
  scrollWrapper.style.padding = "16px";
2843
2948
  scrollWrapper.style.boxSizing = "border-box";
2844
2949
  const sizer = document.createElement("div");
@@ -2849,6 +2954,11 @@ var MediaPlugin = class {
2849
2954
  sizer.style.justifyContent = "center";
2850
2955
  sizer.style.alignItems = "center";
2851
2956
  sizer.style.margin = "auto 0";
2957
+ if (isAudio) {
2958
+ sizer.style.width = "100%";
2959
+ sizer.style.maxWidth = "520px";
2960
+ sizer.style.margin = "auto";
2961
+ }
2852
2962
  sizer.appendChild(element);
2853
2963
  scrollWrapper.appendChild(sizer);
2854
2964
  ctx.container.style.overflow = "auto";
@@ -2907,7 +3017,9 @@ var MediaPlugin = class {
2907
3017
  element.style.transformOrigin = "center center";
2908
3018
  element.style.flexShrink = "0";
2909
3019
  } else {
2910
- element.style.transform = `scale(${currentZoom}) rotate(${rotation}deg)`;
3020
+ if (!isAudio) {
3021
+ element.style.transform = `scale(${currentZoom}) rotate(${rotation}deg)`;
3022
+ }
2911
3023
  }
2912
3024
  };
2913
3025
  updateBaseDimensions();
@@ -2933,6 +3045,10 @@ var MediaPlugin = class {
2933
3045
  ro?.observe(ctx.container);
2934
3046
  const cleanup = () => {
2935
3047
  ro?.disconnect();
3048
+ if (mediaElement) {
3049
+ mediaElement.pause();
3050
+ mediaElement.src = "";
3051
+ }
2936
3052
  if (url) URL.revokeObjectURL(url);
2937
3053
  scrollWrapper.remove();
2938
3054
  ctx.container.innerHTML = "";
@@ -2956,36 +3072,54 @@ var MediaPlugin = class {
2956
3072
  currentZoom = level;
2957
3073
  applyTransform();
2958
3074
  } : void 0,
2959
- fitToPage: isImage || isVideo ? () => {
2960
- isUserZoomed = false;
2961
- fitMode = "page";
2962
- currentZoom = 1;
2963
- rotation = 0;
2964
- ctx.container.scrollTop = 0;
2965
- ctx.container.scrollLeft = 0;
2966
- updateBaseDimensions();
2967
- applyTransform();
2968
- } : void 0,
2969
- fitToWidth: isImage || isVideo ? () => {
2970
- isUserZoomed = false;
2971
- fitMode = "width";
2972
- currentZoom = 1;
2973
- rotation = 0;
2974
- ctx.container.scrollTop = 0;
2975
- ctx.container.scrollLeft = 0;
2976
- updateBaseDimensions();
2977
- applyTransform();
2978
- } : void 0,
2979
- resetZoom: isImage || isVideo ? () => {
2980
- isUserZoomed = false;
2981
- fitMode = ctx?.options?.fitMode || "width";
2982
- currentZoom = 1;
2983
- rotation = 0;
2984
- ctx.container.scrollTop = 0;
2985
- ctx.container.scrollLeft = 0;
2986
- updateBaseDimensions();
2987
- applyTransform();
2988
- } : void 0,
3075
+ fitToPage: () => {
3076
+ if (isImage || isVideo) {
3077
+ isUserZoomed = false;
3078
+ fitMode = "page";
3079
+ currentZoom = 1;
3080
+ rotation = 0;
3081
+ ctx.container.scrollTop = 0;
3082
+ ctx.container.scrollLeft = 0;
3083
+ updateBaseDimensions();
3084
+ applyTransform();
3085
+ } else if (isAudio) {
3086
+ ctx.container.scrollTop = 0;
3087
+ ctx.container.scrollLeft = 0;
3088
+ currentZoom = 1;
3089
+ }
3090
+ },
3091
+ fitToWidth: () => {
3092
+ if (isImage || isVideo) {
3093
+ isUserZoomed = false;
3094
+ fitMode = "width";
3095
+ currentZoom = 1;
3096
+ rotation = 0;
3097
+ ctx.container.scrollTop = 0;
3098
+ ctx.container.scrollLeft = 0;
3099
+ updateBaseDimensions();
3100
+ applyTransform();
3101
+ } else if (isAudio) {
3102
+ ctx.container.scrollTop = 0;
3103
+ ctx.container.scrollLeft = 0;
3104
+ currentZoom = 1;
3105
+ }
3106
+ },
3107
+ resetZoom: () => {
3108
+ if (isImage || isVideo) {
3109
+ isUserZoomed = false;
3110
+ fitMode = ctx?.options?.fitMode || "width";
3111
+ currentZoom = 1;
3112
+ rotation = 0;
3113
+ ctx.container.scrollTop = 0;
3114
+ ctx.container.scrollLeft = 0;
3115
+ updateBaseDimensions();
3116
+ applyTransform();
3117
+ } else if (isAudio) {
3118
+ ctx.container.scrollTop = 0;
3119
+ ctx.container.scrollLeft = 0;
3120
+ currentZoom = 1;
3121
+ }
3122
+ },
2989
3123
  rotateCW: isImage || isVideo ? () => {
2990
3124
  rotation = (rotation + 90) % 360;
2991
3125
  applyTransform();