最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

svelte - Why my chrome extension is crashing during upload of image when Chrome is maximised? - Stack Overflow

programmeradmin1浏览0评论

I am using svelte to build a chrome extension which has the ability to upload images and Post that image to instagram. Here is my project directory structure.

├── .git/
├── .gitignore
├── .npmrc
├── README.md
├── package.json
├── src/
│   ├── app.d.ts
│   ├── app.html
│   ├── lib/
│   │   ├── components/
│   │   │   ├── Button.svelte
│   │   │   ├── CaptionEditor.svelte
│   │   │   ├── HashTagsEditor.svelte
│   │   │   ├── ImagePreview.svelte
│   │   │   ├── ImageUploader.svelte
│   │   │   ├── PostsTab.svelte
│   │   │   ├── ScheduledTab.svelte
│   │   │   ├── StatsTab.svelte
│   │   │   └── Tabs.svelte
│   │   └── index.ts
│   └── routes/
│       ├── +layout.ts
│       └── +page.svelte
├── static/
│   ├── favicon.png
│   ├── manifest.json
│   └── popup.css
├── svelte.config.js
├── tsconfig.json
└── vite.config.ts

I am using pnpm. Interstingly when i drag and drop the image it is able to show preview, also when the chrome is not fully expanded, even in the case when i click on extension and right click inspect that case also it is able to upload the file and show me the preview. The file size is not the issue as for drag and drop i have uploaded a 1KB and 1.2MB file This is my manifest.json file.{

    "manifest_version":3,
    "name":"instoma",
    "version":"0.0.1",
    "description": "A simple instagram automation tool",
    "action":{
        "default_popup":"index.html"
    },
    "permissions":[
        "storage",
        "unlimitedStorage"
    ],
    "web_accessible_resources": [
        {
            "resources": [
                "*.png",
                "*.jpg",
                "*.jpeg"
            ],
            "matches": [
                "<all_urls>"
            ]
        }
    ],
    "content_security_policy": {
        "extension_pages": "script-src 'self'; object-src 'self'"
    }
}

This is my popup.css file.

body {
    width: 450px;
    height: 600px;
    margin: 0;
    padding: 0;
    overflow: auto;
    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
}

/* Add this to ensure the extension doesn't collapse */
html, body {
    min-height: 400px;
    max-height: 600px;
}

/* Fix for Chrome fullscreen mode */
@media (min-height: 800px) {
    body {
        height: 600px;
        overflow: hidden;
    }
}

/* Add these styles to improve stability */
.plugin-container {
    height: 100%;
    max-height: 580px;
    overflow: hidden;
    display: flex;
    flex-direction: column;
}

.tab-content {
    overflow: auto;
    max-height: calc(100% - 100px);
    flex: 1;
}

/* Add this to prevent memory issues with images */
img {
    max-width: 100%;
    height: auto;
    object-fit: contain;
}

This is my +page.svelte file.

<svelte:head>
    <link rel="stylesheet" href="popup.css"/>
</svelte:head>

<script>
  import { onMount } from 'svelte';
  import Tabs from '$lib/components/Tabs.svelte';
  import PostsTab from '$lib/components/PostsTab.svelte';
  import ScheduledTab from '$lib/components/ScheduledTab.svelte';
  import StatsTab from '$lib/components/StatsTab.svelte';
  
  let activeTab = $state('POSTS');
  let error = $state(null);
  
  const tabs = [
    { id: 'POSTS', label: 'POSTS' },
    { id: 'SCHEDULED', label: 'SCHEDULED' },
    { id: 'STATS', label: 'STATS' }
  ];
  
  // Add global error handler
  onMount(() => {
    window.addEventListener('error', (event) => {
      console.error('Global error:', event.error);
      error = event.error?.message || 'Unknown error occurred';
      return false;
    });
    
    window.addEventListener('unhandledrejection', (event) => {
      console.error('Unhandled promise rejection:', event.reason);
      error = event.reason?.message || 'Promise rejection occurred';
      return false;
    });
  });
</script>

<main>
  <div class="plugin-container">
    {#if error}
      <div class="error-container">
        <h3>Something went wrong</h3>
        <p>{error}</p>
        <button on:click={() => error = null}>Dismiss</button>
      </div>
    {:else}
      <Tabs {tabs} bind:activeTab />
      <p class="active-tab-display">The active tab is {activeTab}</p>
      
      <div class="tab-content">
        {#if activeTab === 'POSTS'}
          <PostsTab />
        {:else if activeTab === 'SCHEDULED'}
          <ScheduledTab />
        {:else if activeTab === 'STATS'}
          <StatsTab />
        {/if}
      </div>
    {/if}
  </div>
</main>

<style>
  main {
    font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    padding: 1rem;
    max-width: 100%;
    margin: 0 auto;
    box-sizing: border-box;
    height: 100%;
  }
  
  .plugin-container {
    background-color: #fff;
    border-radius: 16px;
    box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
    overflow: hidden;
    height: 100%;
    display: flex;
    flex-direction: column;
  }
  
  .tab-content {
    flex: 1;
    overflow: auto;
    padding: 1rem;
  }
  
  .active-tab-display {
    color: peru;
    font-size: 1.5rem;
    margin: 0.5rem 0;
    text-align: center;
    background-color: #f0f0f0;
    padding: 0.5rem;
    border-radius: 8px;
  }
  
  .error-container {
    padding: 2rem;
    text-align: center;
    color: #d32f2f;
  }
  
  .error-container button {
    margin-top: 1rem;
    padding: 0.5rem 1rem;
    background-color: #f0f0f0;
    border: none;
    border-radius: 4px;
    cursor: pointer;
  }
</style>

This is my ImageUploader.svelte file.

<script lang="ts">
  import { createEventDispatcher } from "svelte";
  let isDragging = $state(false);
  let fileInput: HTMLInputElement;
  
  const dispatch = createEventDispatcher<{
    upload: { url: string };
  }>();

  function processFile(file: File) {
    // Check file type
    if (!file.type.match('image.*')) return;
    
    // Check file size (5MB limit)
    if (file.size > 5 * 1024 * 1024) {
      alert(`File ${file.name} is too large. Maximum size is 5MB.`);
      return;
    }
    
    // Use a simple approach that's less likely to cause issues
    const reader = new FileReader();
    
    reader.onload = (e) => {
      if (typeof e.target?.result !== 'string') return;
      dispatch("upload", { url: e.target.result });
    };
    
    reader.onerror = () => {
      console.error("Error reading file");
    };
    
    reader.readAsDataURL(file);
  }

  function handleFileUpload(event: Event) {
    try {
      const input = event.target as HTMLInputElement;
      const files = input.files;
      if (!files || files.length === 0) return;
      
      if (files.length > 3) {
        alert("You can only upload up to 3 images at a time.");
        return;
      }
      
      for (const file of files) {
        processFile(file);
      }
      
      // Reset the input to allow selecting the same file again
      input.value = '';
    } catch (error) {
      console.error("Error in file upload:", error);
    }
  }
  
  function handleDragOver(event: DragEvent) {
    event.preventDefault();
    isDragging = true;
  }
  
  function handleDragLeave() {
    isDragging = false;
  }
  
  function handleDrop(event: DragEvent) {
    event.preventDefault();
    isDragging = false;
    
    try {
      const files = event.dataTransfer?.files;
      if(!files || files.length === 0) return;

      if (files.length > 3) {
        alert("You can only upload up to 3 images at a time.");
        return;
      }
      
      for (const file of files) {
        processFile(file);
      }
    } catch (error) {
      console.error("Error in drop handling:", error);
    }
  }
  
  function handleClick() {
    if (fileInput) {
      fileInput.click();
    }
  }
</script>

<div
  class="uploader {isDragging ? 'dragging' : ''}"
  role="button"
  aria-label="Upload images"
  on:click={handleClick}
  on:dragover={handleDragOver}
  on:dragleave={handleDragLeave}
  on:drop={handleDrop}
>
  <input
    type="file"
    hidden
    bind:this={fileInput}
    on:change={handleFileUpload}
    accept=".jpg, .jpeg, .png"
    multiple
  />

  <div class="upload-content">
    <svg
      xmlns=";
      width="36"
      height="36"
      viewBox="0 0 24 24"
      fill="none"
      stroke="currentColor"
      stroke-width="2"
      stroke-linecap="round"
      stroke-linejoin="round"
    >
      <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path>
      <polyline points="17 8 12 3 7 8"></polyline>
      <line x1="12" y1="3" x2="12" y2="15"></line>
    </svg>
    <p>Drag & drop images here or <span>browse</span></p>
    <small>Supports JPG, JPEG, PNG (max 3 images)</small>
  </div>
</div>

<style>
  .uploader {
    border: 2px dashed #ccc;
    border-radius: 12px;
    padding: 2rem;
    text-align: center;
    cursor: pointer;
    transition: all 0.2s ease;
  }
  
  .uploader:hover {
    border-color: #007bff;
  }
  
  .uploader.dragging {
    border-color: #007bff;
    background-color: rgba(0, 123, 255, 0.05);
    transform: scale(1.01);
  }

  .upload-content {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 1rem;
    color: #666;
  }

  span {
    color: #007bff;
    font-weight: 500;
  }
</style>

This is my ImagePreview.svelte file.

<script lang="ts">
  import CaptionEditor from "./CaptionEditor.svelte";
  import HashTagsEditor from "./HashTagsEditor.svelte";
  import Button from "./Button.svelte";
  import { CircleX } from '@lucide/svelte';
  import { createEventDispatcher } from 'svelte';

  interface PostResult {
    success: boolean | null;
    message: string;
  }
  const { image, index } = $props();
  const dispatch = createEventDispatcher();

  let showCaption = $state(false);
  let showHashtags = $state(false);
  let isPosting = $state(false);
  let postResult = $state<PostResult>({ success: null, message: '' });

  async function shareImage() {
    try {
      isPosting = true;
      postResult = { success: null, message: 'Posting to Instagram...' };
      
      const response = await fetch('http://localhost:8188/api/instagram/post', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({
          imageUrl: image.url,
          caption: image.caption,
          hashtags: image.hashtags
        })
      });
      
      const result = await response.json();
      
      if (result.success) {
        postResult = { success: true, message: 'Posted successfully to Instagram!' };
      } else {
        postResult = { success: false, message: `Error: ${result.message}` };
        console.error('Error posting to Instagram:', result.message);
        console.log("-----");
        console.log(postResult);
      }
    } catch (error) {
      console.error('Error sharing image:', error);
      postResult = { success: false, message: `Error: ${error.message}` };
      console.log("*********");
      console.log(postResult);
    } finally {
      isPosting = false;
      // Clear result message after 5 seconds
      setTimeout(() => {
        postResult = { success: null, message: '' };
      }, 60000);
    }
  }
  function handleRemove() {
    dispatch('remove', index);
  }
</script>

<div class="image-preview">
  <div class="image-container">
    <img src={image.url} alt="Demo post preview" />
    <button class="close-button" on:click|stopPropagation={handleRemove} aria-label="Remove image">
      <CircleX size={24} />
    </button>
  </div>

  <div class="content">
    <h3>Image {index + 1}</h3>
    <div class="actions">
      <button on:click={shareImage} class="action-button" disabled={isPosting}>
        <svg
          xmlns=";
          width="24"
          height="24"
          viewBox="0 0 24 24"
          fill="none"
          stroke="currentColor"
          stroke-width="2"
          stroke-linecap="round"
          stroke-linejoin="round"
        >
          <path d="M4 12v8a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-8"></path>
          <polyline points="16 6 12 2 8 6"></polyline>
          <line x1="12" y1="2" x2="12" y2="15"></line>
        </svg>
      </button>
      <button
        on:click={() => (showCaption = !showCaption)}
        class="action-button"
      >
        <svg
          xmlns=";
          width="24"
          height="24"
          viewBox="0 0 24 24"
          fill="none"
          stroke="currentColor"
          stroke-width="2"
          stroke-linecap="round"
          stroke-linejoin="round"
        >
          <path d="M12 20h9"></path>
          <path d="M16.5 3.5a2.121 2.121 0 0 1 3 3L7 19l-4 1 1-4L16.5 3.5z"
          ></path>
        </svg>
      </button>
      <button
        on:click={() => (showHashtags = !showHashtags)}
        class="action-button"
      >
        <svg
          xmlns=";
          width="24"
          height="24"
          viewBox="0 0 24 24"
          fill="none"
          stroke="currentColor"
          stroke-width="2"
          stroke-linecap="round"
          stroke-linejoin="round"
        >
          <path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"
          ></path>
          <path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"
          ></path>
        </svg>
      </button>
    </div>
    
    {#if postResult.message}
      <div class="post-result {postResult.success ? 'success' : postResult.success === false ? 'error' : 'info'}">
        {postResult.message}
      </div>
    {/if}
    
    {#if showCaption}
      <CaptionEditor {image} />
    {/if}

    {#if showHashtags}
      <HashTagsEditor {image} />
    {/if}
  </div>
</div>

<style>
  .image-preview {
    background-color: white;
    border-radius: 12px;
    overflow: hidden;
    box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
    display: flex;
    flex-direction: column;
    padding: 1rem;
  }
  
  .image-container {
    position: relative;
    width: 100%;
    padding-top: 100%; /* 1:1 Aspect Ratio */
    overflow: hidden;
  }
  
  img {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
  }
  
  .close-button {
    position: absolute;
    top: 8px;
    right: 8px;
    background: rgba(255, 255, 255, 0.7);
    border: none;
    border-radius: 50%;
    width: 32px;
    height: 32px;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition: all 0.2s ease;
    padding: 0;
    z-index: 10;
  }
  
  .close-button:hover {
    background: rgba(255, 255, 255, 0.9);
    transform: scale(1.1);
  }
  
  .close-button:hover :global(svg) {
    color: #ff3333;
  }
  
  .content {
    padding: 1rem;
  }
  
  h3 {
    margin: 0 0 1rem 0;
    font-size: 1.2rem;
    color: #262626;
  }
  
  .actions {
    display: flex;
    gap: 0.75rem;
    margin-bottom: 1rem;
  }
  
  .action-button {
    background: none;
    border: none;
    cursor: pointer;
    padding: 0.5rem;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: background-color 0.2s;
  }
  
  .action-button:hover {
    background-color: #f0f0f0;
  }
  
  .action-button[disabled] {
    opacity: 0.5;
    cursor: not-allowed;
  }
  
  .post-result {
    padding: 0.75rem;
    border-radius: 8px;
    margin-bottom: 1rem;
    font-size: 0.9rem;
  }
  
  .post-result.success {
    background-color: #e3f7e8;
    color: #2e7d32;
  }
  
  .post-result.error {
    background-color: #fdecea;
    color: #d32f2f;
  }
  
  .post-result.info {
    background-color: #e8f4fd;
    color: #0277bd;
  }
</style>

I have disabled all other extensions.Still not able to figure out the issue. What am i missing here, are the styles causing conflicts or issues ?

I am using svelte to build a chrome extension which has the ability to upload images and Post that image to instagram. Here is my project directory structure.

├── .git/
├── .gitignore
├── .npmrc
├── README.md
├── package.json
├── src/
│   ├── app.d.ts
│   ├── app.html
│   ├── lib/
│   │   ├── components/
│   │   │   ├── Button.svelte
│   │   │   ├── CaptionEditor.svelte
│   │   │   ├── HashTagsEditor.svelte
│   │   │   ├── ImagePreview.svelte
│   │   │   ├── ImageUploader.svelte
│   │   │   ├── PostsTab.svelte
│   │   │   ├── ScheduledTab.svelte
│   │   │   ├── StatsTab.svelte
│   │   │   └── Tabs.svelte
│   │   └── index.ts
│   └── routes/
│       ├── +layout.ts
│       └── +page.svelte
├── static/
│   ├── favicon.png
│   ├── manifest.json
│   └── popup.css
├── svelte.config.js
├── tsconfig.json
└── vite.config.ts

I am using pnpm. Interstingly when i drag and drop the image it is able to show preview, also when the chrome is not fully expanded, even in the case when i click on extension and right click inspect that case also it is able to upload the file and show me the preview. The file size is not the issue as for drag and drop i have uploaded a 1KB and 1.2MB file This is my manifest.json file.{

    "manifest_version":3,
    "name":"instoma",
    "version":"0.0.1",
    "description": "A simple instagram automation tool",
    "action":{
        "default_popup":"index.html"
    },
    "permissions":[
        "storage",
        "unlimitedStorage"
    ],
    "web_accessible_resources": [
        {
            "resources": [
                "*.png",
                "*.jpg",
                "*.jpeg"
            ],
            "matches": [
                "<all_urls>"
            ]
        }
    ],
    "content_security_policy": {
        "extension_pages": "script-src 'self'; object-src 'self'"
    }
}

This is my popup.css file.

body {
    width: 450px;
    height: 600px;
    margin: 0;
    padding: 0;
    overflow: auto;
    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
}

/* Add this to ensure the extension doesn't collapse */
html, body {
    min-height: 400px;
    max-height: 600px;
}

/* Fix for Chrome fullscreen mode */
@media (min-height: 800px) {
    body {
        height: 600px;
        overflow: hidden;
    }
}

/* Add these styles to improve stability */
.plugin-container {
    height: 100%;
    max-height: 580px;
    overflow: hidden;
    display: flex;
    flex-direction: column;
}

.tab-content {
    overflow: auto;
    max-height: calc(100% - 100px);
    flex: 1;
}

/* Add this to prevent memory issues with images */
img {
    max-width: 100%;
    height: auto;
    object-fit: contain;
}

This is my +page.svelte file.

<svelte:head>
    <link rel="stylesheet" href="popup.css"/>
</svelte:head>

<script>
  import { onMount } from 'svelte';
  import Tabs from '$lib/components/Tabs.svelte';
  import PostsTab from '$lib/components/PostsTab.svelte';
  import ScheduledTab from '$lib/components/ScheduledTab.svelte';
  import StatsTab from '$lib/components/StatsTab.svelte';
  
  let activeTab = $state('POSTS');
  let error = $state(null);
  
  const tabs = [
    { id: 'POSTS', label: 'POSTS' },
    { id: 'SCHEDULED', label: 'SCHEDULED' },
    { id: 'STATS', label: 'STATS' }
  ];
  
  // Add global error handler
  onMount(() => {
    window.addEventListener('error', (event) => {
      console.error('Global error:', event.error);
      error = event.error?.message || 'Unknown error occurred';
      return false;
    });
    
    window.addEventListener('unhandledrejection', (event) => {
      console.error('Unhandled promise rejection:', event.reason);
      error = event.reason?.message || 'Promise rejection occurred';
      return false;
    });
  });
</script>

<main>
  <div class="plugin-container">
    {#if error}
      <div class="error-container">
        <h3>Something went wrong</h3>
        <p>{error}</p>
        <button on:click={() => error = null}>Dismiss</button>
      </div>
    {:else}
      <Tabs {tabs} bind:activeTab />
      <p class="active-tab-display">The active tab is {activeTab}</p>
      
      <div class="tab-content">
        {#if activeTab === 'POSTS'}
          <PostsTab />
        {:else if activeTab === 'SCHEDULED'}
          <ScheduledTab />
        {:else if activeTab === 'STATS'}
          <StatsTab />
        {/if}
      </div>
    {/if}
  </div>
</main>

<style>
  main {
    font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    padding: 1rem;
    max-width: 100%;
    margin: 0 auto;
    box-sizing: border-box;
    height: 100%;
  }
  
  .plugin-container {
    background-color: #fff;
    border-radius: 16px;
    box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
    overflow: hidden;
    height: 100%;
    display: flex;
    flex-direction: column;
  }
  
  .tab-content {
    flex: 1;
    overflow: auto;
    padding: 1rem;
  }
  
  .active-tab-display {
    color: peru;
    font-size: 1.5rem;
    margin: 0.5rem 0;
    text-align: center;
    background-color: #f0f0f0;
    padding: 0.5rem;
    border-radius: 8px;
  }
  
  .error-container {
    padding: 2rem;
    text-align: center;
    color: #d32f2f;
  }
  
  .error-container button {
    margin-top: 1rem;
    padding: 0.5rem 1rem;
    background-color: #f0f0f0;
    border: none;
    border-radius: 4px;
    cursor: pointer;
  }
</style>

This is my ImageUploader.svelte file.

<script lang="ts">
  import { createEventDispatcher } from "svelte";
  let isDragging = $state(false);
  let fileInput: HTMLInputElement;
  
  const dispatch = createEventDispatcher<{
    upload: { url: string };
  }>();

  function processFile(file: File) {
    // Check file type
    if (!file.type.match('image.*')) return;
    
    // Check file size (5MB limit)
    if (file.size > 5 * 1024 * 1024) {
      alert(`File ${file.name} is too large. Maximum size is 5MB.`);
      return;
    }
    
    // Use a simple approach that's less likely to cause issues
    const reader = new FileReader();
    
    reader.onload = (e) => {
      if (typeof e.target?.result !== 'string') return;
      dispatch("upload", { url: e.target.result });
    };
    
    reader.onerror = () => {
      console.error("Error reading file");
    };
    
    reader.readAsDataURL(file);
  }

  function handleFileUpload(event: Event) {
    try {
      const input = event.target as HTMLInputElement;
      const files = input.files;
      if (!files || files.length === 0) return;
      
      if (files.length > 3) {
        alert("You can only upload up to 3 images at a time.");
        return;
      }
      
      for (const file of files) {
        processFile(file);
      }
      
      // Reset the input to allow selecting the same file again
      input.value = '';
    } catch (error) {
      console.error("Error in file upload:", error);
    }
  }
  
  function handleDragOver(event: DragEvent) {
    event.preventDefault();
    isDragging = true;
  }
  
  function handleDragLeave() {
    isDragging = false;
  }
  
  function handleDrop(event: DragEvent) {
    event.preventDefault();
    isDragging = false;
    
    try {
      const files = event.dataTransfer?.files;
      if(!files || files.length === 0) return;

      if (files.length > 3) {
        alert("You can only upload up to 3 images at a time.");
        return;
      }
      
      for (const file of files) {
        processFile(file);
      }
    } catch (error) {
      console.error("Error in drop handling:", error);
    }
  }
  
  function handleClick() {
    if (fileInput) {
      fileInput.click();
    }
  }
</script>

<div
  class="uploader {isDragging ? 'dragging' : ''}"
  role="button"
  aria-label="Upload images"
  on:click={handleClick}
  on:dragover={handleDragOver}
  on:dragleave={handleDragLeave}
  on:drop={handleDrop}
>
  <input
    type="file"
    hidden
    bind:this={fileInput}
    on:change={handleFileUpload}
    accept=".jpg, .jpeg, .png"
    multiple
  />

  <div class="upload-content">
    <svg
      xmlns="http://www.w3./2000/svg"
      width="36"
      height="36"
      viewBox="0 0 24 24"
      fill="none"
      stroke="currentColor"
      stroke-width="2"
      stroke-linecap="round"
      stroke-linejoin="round"
    >
      <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path>
      <polyline points="17 8 12 3 7 8"></polyline>
      <line x1="12" y1="3" x2="12" y2="15"></line>
    </svg>
    <p>Drag & drop images here or <span>browse</span></p>
    <small>Supports JPG, JPEG, PNG (max 3 images)</small>
  </div>
</div>

<style>
  .uploader {
    border: 2px dashed #ccc;
    border-radius: 12px;
    padding: 2rem;
    text-align: center;
    cursor: pointer;
    transition: all 0.2s ease;
  }
  
  .uploader:hover {
    border-color: #007bff;
  }
  
  .uploader.dragging {
    border-color: #007bff;
    background-color: rgba(0, 123, 255, 0.05);
    transform: scale(1.01);
  }

  .upload-content {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 1rem;
    color: #666;
  }

  span {
    color: #007bff;
    font-weight: 500;
  }
</style>

This is my ImagePreview.svelte file.

<script lang="ts">
  import CaptionEditor from "./CaptionEditor.svelte";
  import HashTagsEditor from "./HashTagsEditor.svelte";
  import Button from "./Button.svelte";
  import { CircleX } from '@lucide/svelte';
  import { createEventDispatcher } from 'svelte';

  interface PostResult {
    success: boolean | null;
    message: string;
  }
  const { image, index } = $props();
  const dispatch = createEventDispatcher();

  let showCaption = $state(false);
  let showHashtags = $state(false);
  let isPosting = $state(false);
  let postResult = $state<PostResult>({ success: null, message: '' });

  async function shareImage() {
    try {
      isPosting = true;
      postResult = { success: null, message: 'Posting to Instagram...' };
      
      const response = await fetch('http://localhost:8188/api/instagram/post', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({
          imageUrl: image.url,
          caption: image.caption,
          hashtags: image.hashtags
        })
      });
      
      const result = await response.json();
      
      if (result.success) {
        postResult = { success: true, message: 'Posted successfully to Instagram!' };
      } else {
        postResult = { success: false, message: `Error: ${result.message}` };
        console.error('Error posting to Instagram:', result.message);
        console.log("-----");
        console.log(postResult);
      }
    } catch (error) {
      console.error('Error sharing image:', error);
      postResult = { success: false, message: `Error: ${error.message}` };
      console.log("*********");
      console.log(postResult);
    } finally {
      isPosting = false;
      // Clear result message after 5 seconds
      setTimeout(() => {
        postResult = { success: null, message: '' };
      }, 60000);
    }
  }
  function handleRemove() {
    dispatch('remove', index);
  }
</script>

<div class="image-preview">
  <div class="image-container">
    <img src={image.url} alt="Demo post preview" />
    <button class="close-button" on:click|stopPropagation={handleRemove} aria-label="Remove image">
      <CircleX size={24} />
    </button>
  </div>

  <div class="content">
    <h3>Image {index + 1}</h3>
    <div class="actions">
      <button on:click={shareImage} class="action-button" disabled={isPosting}>
        <svg
          xmlns="http://www.w3./2000/svg"
          width="24"
          height="24"
          viewBox="0 0 24 24"
          fill="none"
          stroke="currentColor"
          stroke-width="2"
          stroke-linecap="round"
          stroke-linejoin="round"
        >
          <path d="M4 12v8a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-8"></path>
          <polyline points="16 6 12 2 8 6"></polyline>
          <line x1="12" y1="2" x2="12" y2="15"></line>
        </svg>
      </button>
      <button
        on:click={() => (showCaption = !showCaption)}
        class="action-button"
      >
        <svg
          xmlns="http://www.w3./2000/svg"
          width="24"
          height="24"
          viewBox="0 0 24 24"
          fill="none"
          stroke="currentColor"
          stroke-width="2"
          stroke-linecap="round"
          stroke-linejoin="round"
        >
          <path d="M12 20h9"></path>
          <path d="M16.5 3.5a2.121 2.121 0 0 1 3 3L7 19l-4 1 1-4L16.5 3.5z"
          ></path>
        </svg>
      </button>
      <button
        on:click={() => (showHashtags = !showHashtags)}
        class="action-button"
      >
        <svg
          xmlns="http://www.w3./2000/svg"
          width="24"
          height="24"
          viewBox="0 0 24 24"
          fill="none"
          stroke="currentColor"
          stroke-width="2"
          stroke-linecap="round"
          stroke-linejoin="round"
        >
          <path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"
          ></path>
          <path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"
          ></path>
        </svg>
      </button>
    </div>
    
    {#if postResult.message}
      <div class="post-result {postResult.success ? 'success' : postResult.success === false ? 'error' : 'info'}">
        {postResult.message}
      </div>
    {/if}
    
    {#if showCaption}
      <CaptionEditor {image} />
    {/if}

    {#if showHashtags}
      <HashTagsEditor {image} />
    {/if}
  </div>
</div>

<style>
  .image-preview {
    background-color: white;
    border-radius: 12px;
    overflow: hidden;
    box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
    display: flex;
    flex-direction: column;
    padding: 1rem;
  }
  
  .image-container {
    position: relative;
    width: 100%;
    padding-top: 100%; /* 1:1 Aspect Ratio */
    overflow: hidden;
  }
  
  img {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
  }
  
  .close-button {
    position: absolute;
    top: 8px;
    right: 8px;
    background: rgba(255, 255, 255, 0.7);
    border: none;
    border-radius: 50%;
    width: 32px;
    height: 32px;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition: all 0.2s ease;
    padding: 0;
    z-index: 10;
  }
  
  .close-button:hover {
    background: rgba(255, 255, 255, 0.9);
    transform: scale(1.1);
  }
  
  .close-button:hover :global(svg) {
    color: #ff3333;
  }
  
  .content {
    padding: 1rem;
  }
  
  h3 {
    margin: 0 0 1rem 0;
    font-size: 1.2rem;
    color: #262626;
  }
  
  .actions {
    display: flex;
    gap: 0.75rem;
    margin-bottom: 1rem;
  }
  
  .action-button {
    background: none;
    border: none;
    cursor: pointer;
    padding: 0.5rem;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: background-color 0.2s;
  }
  
  .action-button:hover {
    background-color: #f0f0f0;
  }
  
  .action-button[disabled] {
    opacity: 0.5;
    cursor: not-allowed;
  }
  
  .post-result {
    padding: 0.75rem;
    border-radius: 8px;
    margin-bottom: 1rem;
    font-size: 0.9rem;
  }
  
  .post-result.success {
    background-color: #e3f7e8;
    color: #2e7d32;
  }
  
  .post-result.error {
    background-color: #fdecea;
    color: #d32f2f;
  }
  
  .post-result.info {
    background-color: #e8f4fd;
    color: #0277bd;
  }
</style>

I have disabled all other extensions.Still not able to figure out the issue. What am i missing here, are the styles causing conflicts or issues ?

Share Improve this question asked Mar 12 at 15:28 Danish XavierDanish Xavier 1,1661 gold badge13 silver badges21 bronze badges 1
  • what exactly does "crashing" mean in that context? – derpirscher Commented Mar 21 at 12:40
Add a comment  | 

1 Answer 1

Reset to default -1

Try running your extension as a standalone tab or sidebar action instead of a popup:

"action": {
  "default_popup": "index.html"
},
"sidebar_action": {
  "default_page": "index.html"
}

Use a background script to persist images before the popup closes:

"background": {
  "service_worker": "background.js"
}

Add logic to save and retrieve the image from chrome.storage.local.

<script>
  import { onMount } from "svelte";

  let imageUrl = "";

  // Handle file selection
  function handleFileUpload(event) {
    const file = event.target.files[0];
    if (file) {
      const reader = new FileReader();
      reader.onload = () => {
        imageUrl = reader.result;
        chrome.storage.local.set({ uploadedImage: imageUrl });
      };
      reader.readAsDataURL(file);
    }
  }

  // Retrieve image on mount
  onMount(() => {
    chrome.storage.local.get("uploadedImage", (data) => {
      if (data.uploadedImage) {
        imageUrl = data.uploadedImage;
      }
    });
  });
</script>

<input type="file" accept="image/*" on:change={handleFileUpload} />
{#if imageUrl}
  <img src={imageUrl} alt="Uploaded Preview" style="max-width: 100%;" />
{/if}

Ensure you have storage permission in manifest.json:

{
  "manifest_version": 3,
  "name": "Image Upload Extension",
  "version": "1.0",
  "permissions": ["storage"]
}
发布评论

评论列表(0)

  1. 暂无评论