app.tsx 4.31 KB
Newer Older
Jeffrey Morgan's avatar
Jeffrey Morgan committed
1
import { useState } from 'react'
2
import copy from 'copy-to-clipboard'
Eva Ho's avatar
Eva Ho committed
3
import { CheckIcon, DocumentDuplicateIcon } from '@heroicons/react/24/outline'
4
5
import Store from 'electron-store'
import { getCurrentWindow } from '@electron/remote'
Jeffrey Morgan's avatar
Jeffrey Morgan committed
6

7
8
import { install } from './install'
import OllamaIcon from './ollama.svg'
Jeffrey Morgan's avatar
Jeffrey Morgan committed
9

10
const store = new Store()
Jeffrey Morgan's avatar
Jeffrey Morgan committed
11

Jeffrey Morgan's avatar
Jeffrey Morgan committed
12
13
14
15
16
17
enum Step {
  WELCOME = 0,
  CLI,
  FINISH,
}

Jeffrey Morgan's avatar
Jeffrey Morgan committed
18
export default function () {
Jeffrey Morgan's avatar
Jeffrey Morgan committed
19
  const [step, setStep] = useState<Step>(Step.WELCOME)
Eva Ho's avatar
Eva Ho committed
20
  const [commandCopied, setCommandCopied] = useState<boolean>(false)
21
22

  const command = 'ollama run orca'
Jeffrey Morgan's avatar
Jeffrey Morgan committed
23

Jeffrey Morgan's avatar
Jeffrey Morgan committed
24
  return (
Eva Ho's avatar
Eva Ho committed
25
26
27
28
29
30
31
32
33
    <div className='drag'>
      <div className='mx-auto flex min-h-screen w-full flex-col justify-between bg-white px-4 pt-16'>
        {step === Step.WELCOME && (
          <>
            <div className='mx-auto text-center'>
              <h1 className='mb-6 mt-4 text-2xl tracking-tight text-gray-900'>Welcome to Ollama</h1>
              <p className='mx-auto w-[65%] text-sm text-gray-400'>
                Let's get you up and running with your own large language models.
              </p>
34
              <button
Eva Ho's avatar
Eva Ho committed
35
36
                onClick={() => setStep(Step.CLI)}
                className='no-drag rounded-dm mx-auto my-8 w-[40%] rounded-md bg-black px-4 py-2 text-sm text-white hover:brightness-110'
37
              >
Eva Ho's avatar
Eva Ho committed
38
                Next
39
40
              </button>
            </div>
Eva Ho's avatar
Eva Ho committed
41
42
43
44
45
46
47
48
49
50
51
            <div className='mx-auto'>
              <OllamaIcon />
            </div>
          </>
        )}
        {step === Step.CLI && (
          <>
            <div className='mx-auto flex flex-col space-y-28 text-center'>
              <h1 className='mt-4 text-2xl tracking-tight text-gray-900'>Install the command line</h1>
              <pre className='mx-auto text-4xl text-gray-400'>&gt; ollama</pre>
              <div className='mx-auto'>
52
                <button
Eva Ho's avatar
Eva Ho committed
53
54
55
56
57
                  onClick={async () => {
                    await install()
                    getCurrentWindow().show()
                    getCurrentWindow().focus()
                    setStep(Step.FINISH)
58
                  }}
Eva Ho's avatar
Eva Ho committed
59
                  className='no-drag rounded-dm mx-auto w-[60%] rounded-md bg-black px-4 py-2 text-sm text-white hover:brightness-110'
60
                >
Eva Ho's avatar
Eva Ho committed
61
                  Install
62
                </button>
Eva Ho's avatar
Eva Ho committed
63
64
65
                <p className='mx-auto my-4 w-[70%] text-xs text-gray-400'>
                  You will be prompted for administrator access
                </p>
Jeffrey Morgan's avatar
Jeffrey Morgan committed
66
              </div>
Jeffrey Morgan's avatar
Jeffrey Morgan committed
67
            </div>
Eva Ho's avatar
Eva Ho committed
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
          </>
        )}
        {step === Step.FINISH && (
          <>
            <div className='mx-auto flex flex-col space-y-20 text-center'>
              <h1 className='mt-4 text-2xl tracking-tight text-gray-900'>Run your first model</h1>
              <div className='flex flex-col'>
                <div className='group relative flex items-center'>
                  <pre className='language-none text-2xs w-full rounded-md bg-gray-100 px-4 py-3 text-start leading-normal'>
                    {command}
                  </pre>
                  <button
                    className={`no-drag absolute right-[5px] px-2 py-2 ${commandCopied ? 'text-gray-900 opacity-100 hover:cursor-auto' : 'text-gray-200 opacity-50 hover:cursor-pointer'} hover:text-gray-900 hover:font-bold group-hover:opacity-100`}
                    onClick={() => {
                      copy(command)
                      setCommandCopied(true)
                      setTimeout(() => setCommandCopied(false), 3000)
                    }}
                  >
                    {commandCopied ? (
                      <CheckIcon className='h-4 w-4 text-gray-500 font-bold' />
                    ) : (
                      <DocumentDuplicateIcon className='h-4 w-4 text-gray-500' />
                    )}
                  </button>
                </div>
                <p className='mx-auto my-4 w-[70%] text-xs text-gray-400'>Run this command in your favorite terminal.</p>
              </div>
              <button
                onClick={() => {
                  store.set('first-time-run', true)
                  window.close()
                }}
                className='no-drag rounded-dm mx-auto w-[60%] rounded-md bg-black px-4 py-2 text-sm text-white hover:brightness-110'
              >
                Finish
              </button>
            </div>
          </>
        )}
      </div>
Jeffrey Morgan's avatar
Jeffrey Morgan committed
109
110
    </div>
  )
Jeffrey Morgan's avatar
Jeffrey Morgan committed
111
}