Ver código fonte

app: keep installer in foreground

Jeffrey Morgan 1 ano atrás
pai
commit
f923855906
3 arquivos alterados com 49 adições e 40 exclusões
  1. 12 31
      app/src/app.tsx
  2. 13 9
      app/src/index.ts
  3. 24 0
      app/src/install.ts

+ 12 - 31
app/src/app.tsx

@@ -1,32 +1,13 @@
 import { useState } from 'react'
 import { useState } from 'react'
 import copy from 'copy-to-clipboard'
 import copy from 'copy-to-clipboard'
-import { exec as cbExec } from 'child_process'
-import * as path from 'path'
-import * as fs from 'fs'
 import { DocumentDuplicateIcon } from '@heroicons/react/24/outline'
 import { DocumentDuplicateIcon } from '@heroicons/react/24/outline'
-import { app } from '@electron/remote'
-import OllamaIcon from './ollama.svg'
-import { promisify } from 'util'
-
-const ollama = app.isPackaged ? path.join(process.resourcesPath, 'ollama') : path.resolve(process.cwd(), '..', 'ollama')
-const exec = promisify(cbExec)
-
-async function installCLI() {
-  const symlinkPath = '/usr/local/bin/ollama'
-
-  if (fs.existsSync(symlinkPath) && fs.readlinkSync(symlinkPath) === ollama) {
-    return
-  }
+import Store from 'electron-store'
+import { getCurrentWindow } from '@electron/remote'
 
 
-  const command = `do shell script "ln -F -s ${ollama} /usr/local/bin/ollama" with administrator privileges`
+import { install } from './install'
+import OllamaIcon from './ollama.svg'
 
 
-  try {
-    await exec(`osascript -e '${command}'`)
-  } catch (error) {
-    console.error(`cli: failed to install cli: ${error.message}`)
-    return
-  }
-}
+const store = new Store()
 
 
 enum Step {
 enum Step {
   WELCOME = 0,
   WELCOME = 0,
@@ -40,7 +21,7 @@ export default function () {
   const command = 'ollama run orca'
   const command = 'ollama run orca'
 
 
   return (
   return (
-    <div className='drag mx-auto flex min-h-screen w-full flex-col justify-between bg-white px-4 pt-16'>
+    <div className='mx-auto flex min-h-screen w-full flex-col justify-between bg-white px-4 pt-16'>
       {step === Step.WELCOME && (
       {step === Step.WELCOME && (
         <>
         <>
           <div className='mx-auto text-center'>
           <div className='mx-auto text-center'>
@@ -49,9 +30,7 @@ export default function () {
               Let's get you up and running with your own large language models.
               Let's get you up and running with your own large language models.
             </p>
             </p>
             <button
             <button
-              onClick={() => {
-                setStep(1)
-              }}
+              onClick={() => setStep(Step.CLI)}
               className='rounded-dm mx-auto my-8 w-[40%] rounded-md bg-black px-4 py-2 text-sm text-white hover:brightness-110'
               className='rounded-dm mx-auto my-8 w-[40%] rounded-md bg-black px-4 py-2 text-sm text-white hover:brightness-110'
             >
             >
               Next
               Next
@@ -70,9 +49,10 @@ export default function () {
             <div className='mx-auto'>
             <div className='mx-auto'>
               <button
               <button
                 onClick={async () => {
                 onClick={async () => {
-                  await installCLI()
-                  window.focus()
-                  setStep(2)
+                  await install()
+                  getCurrentWindow().show()
+                  getCurrentWindow().focus()
+                  setStep(Step.FINISH)
                 }}
                 }}
                 className='rounded-dm mx-auto w-[60%] rounded-md bg-black px-4 py-2 text-sm text-white hover:brightness-110'
                 className='rounded-dm mx-auto w-[60%] rounded-md bg-black px-4 py-2 text-sm text-white hover:brightness-110'
               >
               >
@@ -107,6 +87,7 @@ export default function () {
             </div>
             </div>
             <button
             <button
               onClick={() => {
               onClick={() => {
+                store.set('first-time-run', true)
                 window.close()
                 window.close()
               }}
               }}
               className='rounded-dm mx-auto w-[60%] rounded-md bg-black px-4 py-2 text-sm text-white hover:brightness-110'
               className='rounded-dm mx-auto w-[60%] rounded-md bg-black px-4 py-2 text-sm text-white hover:brightness-110'

+ 13 - 9
app/src/index.ts

@@ -6,6 +6,7 @@ import 'winston-daily-rotate-file'
 import * as path from 'path'
 import * as path from 'path'
 
 
 import { analytics, id } from './telemetry'
 import { analytics, id } from './telemetry'
+import { installed, install } from './install'
 
 
 require('@electron/remote/main').initialize()
 require('@electron/remote/main').initialize()
 
 
@@ -40,12 +41,13 @@ function firstRunWindow() {
     frame: false,
     frame: false,
     fullscreenable: false,
     fullscreenable: false,
     resizable: false,
     resizable: false,
-    movable: false,
-    transparent: true,
+    movable: true,
+    show: false,
     webPreferences: {
     webPreferences: {
       nodeIntegration: true,
       nodeIntegration: true,
       contextIsolation: false,
       contextIsolation: false,
     },
     },
+    alwaysOnTop: true,
   })
   })
 
 
   require('@electron/remote/main').enable(welcomeWindow.webContents)
   require('@electron/remote/main').enable(welcomeWindow.webContents)
@@ -53,6 +55,8 @@ function firstRunWindow() {
   // and load the index.html of the app.
   // and load the index.html of the app.
   welcomeWindow.loadURL(MAIN_WINDOW_WEBPACK_ENTRY)
   welcomeWindow.loadURL(MAIN_WINDOW_WEBPACK_ENTRY)
 
 
+  welcomeWindow.on('ready-to-show', () => welcomeWindow.show())
+
   // for debugging
   // for debugging
   // welcomeWindow.webContents.openDevTools()
   // welcomeWindow.webContents.openDevTools()
 
 
@@ -151,15 +155,15 @@ app.on('ready', () => {
   createSystemtray()
   createSystemtray()
   server()
   server()
 
 
-  if (!store.has('first-time-run')) {
-    // This is the first run
-    app.setLoginItemSettings({ openAtLogin: true })
-    firstRunWindow()
-    store.set('first-time-run', true)
-  } else {
-    // The app has been run before
+  if (store.get('first-time-run') && installed()) {
     app.setLoginItemSettings({ openAtLogin: app.getLoginItemSettings().openAtLogin })
     app.setLoginItemSettings({ openAtLogin: app.getLoginItemSettings().openAtLogin })
+    return
   }
   }
+
+  // This is the first run or the CLI is no longer installed
+  app.setLoginItemSettings({ openAtLogin: true })
+
+  firstRunWindow()
 })
 })
 
 
 // Quit when all windows are closed, except on macOS. There, it's common
 // Quit when all windows are closed, except on macOS. There, it's common

+ 24 - 0
app/src/install.ts

@@ -0,0 +1,24 @@
+import * as fs from 'fs'
+import { exec as cbExec } from 'child_process'
+import * as path from 'path'
+import { promisify } from 'util'
+
+const app = process && process.type === 'renderer' ? require('@electron/remote').app : require('electron').app
+const ollama = app.isPackaged ? path.join(process.resourcesPath, 'ollama') : path.resolve(process.cwd(), '..', 'ollama')
+const exec = promisify(cbExec)
+const symlinkPath = '/usr/local/bin/ollama'
+
+export function installed() {
+  return fs.existsSync(symlinkPath) && fs.readlinkSync(symlinkPath) === ollama
+}
+
+export async function install() {
+  const command = `do shell script "ln -F -s ${ollama} ${symlinkPath}" with administrator privileges`
+
+  try {
+    await exec(`osascript -e '${command}'`)
+  } catch (error) {
+    console.error(`cli: failed to install cli: ${error.message}`)
+    return
+  }
+}