Skip to content

Commit

Permalink
feat: Prepare Release 23.2.0 (#560)
Browse files Browse the repository at this point in the history
* Update version to 23.2.0-rc.1

* Use `yarn python` instead of hard-coded script

* Add project logo and move h1 to the top

* Add release instructions with GH Actions

* Update logo and header styles

* Update logo and header styles

* Use bigger logo

* Improve Create release step by reusing release with same tag

* Include a debug .dmg

* Bump to 23.2.0-rc.2

* Add an additional note to release notes about debug artifacts

* Fix chat interaction in desktop by using non-stream method

This fixes #567

* fix: Enable server logs by default and prevent user from editing configurations.

Related to #568

* fix: make loading spinner smaller

* fix: pass copy of buffer to pdf worker

This fixes #565

* fix: give modal z-index to command palette

* Fix issue #570 Chat (and rewrite) window does not reset when changing projects

* Bump to 23.2.0-rc.3

* remove `.only` in test!

* Bump version to 23.2.0-rc.4

* Update references panel buttons for upload/search

* Remove save file action from command palette

* Revert "Fix chat interaction in desktop by using non-stream method"

This reverts commit 9eb60e5.

* Remove [...] arbitrary values

* feat: add alignment prop to Button

* Bump version to 23.2.0-rc.5

* Add support for CORS in the backend API

* Fix stream API call from the desktop by appending the REFSTUDIO_HOST

* Links open in default browser on desktop

* Bump version to 23.2.0-rc.6

* Release 23.2.0

---------

Co-authored-by: Mathis Pierron <mathis.pierron@student-cs.fr>
Co-authored-by: Jessica Voytek <jessica.voytek@gmail.com>
  • Loading branch information
3 people committed Sep 22, 2023
1 parent e7f9011 commit c31c3db
Show file tree
Hide file tree
Showing 24 changed files with 197 additions and 97 deletions.
10 changes: 5 additions & 5 deletions .github/workflows/cut-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,14 +47,14 @@ jobs:
uses: actions/github-script@v6
with:
script: |
const targetTag = `${process.env.PACKAGE_VERSION}`;
// API: https://github.com/octokit/plugin-rest-endpoint-methods.js/tree/main/docs/repos
try {
const existingRelease = await github.rest.repos.getReleaseByTag({
const existingReleases = await github.rest.repos.listReleases({
owner: context.repo.owner,
repo: context.repo.repo,
tag: `${process.env.PACKAGE_VERSION}`
})
return existingRelease.data.id
return existingReleases.data.find(release => release.tag_name === targetTag).id
} catch(err) {
console.log("No existing release found. Creating a new release for tag: " + process.env.PACKAGE_VERSION)
}
Expand Down Expand Up @@ -113,7 +113,7 @@ jobs:
- name: Create Python binary
run: |
poetry run pyinstaller --noconfirm --distpath src-tauri/bin/python python/main.py
yarn python
# start server in the background and verify it's working
# the binary takes time to start up, so we need to wait a bit
Expand All @@ -129,7 +129,7 @@ jobs:
with:
releaseId: ${{ needs.create-release.outputs.release_id }}
args: --verbose --target ${{ matrix.target }}
includeDebug: false
includeDebug: true

# publish-release:
# permissions:
Expand Down
36 changes: 23 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
<p align="center"><picture><img alt="Ref Studio Logo" src="src-tauri/icons/Square107x107Logo.png" /></picture></p>
<h1 align="center">Ref Studio</h1>
<p align="center">An open source text editor optimized for writing that relies on references.</p>

<p align="center">
<a href="https://github.com/refstudio/refstudio/actions/workflows/on-push.yml">
<img src="https://github.com/refstudio/refstudio/actions/workflows/on-push.yml/badge.svg" />
Expand All @@ -7,9 +11,6 @@
</a>
</p>

# Ref Studio

> An open source text editor optimized for writing that relies on references.

![Ref Studio](public/readme/readme-refstudio.png)

Expand Down Expand Up @@ -154,14 +155,31 @@ This project version convention is based in a [Calendar Versioning](https://www.

You should follow the general pattern:

* `YY.N.PATCH`
* `YY.N.PATCH[-PRE_RELEASE]`

So the first version is `23.1.0` and a new release, in the same year, would be `23.2.0`, while a patch for the first version your be `23.1.1`. The first release of 2024 would be `24.1.0`.

You can also append a pre-release tag using [semantic version](https://semver.org/spec/v2.0.0-rc.1.html#spec-item-10) rules by appending a dash and a series of dot separated identifiers (ex: `23.2.0-rc.1`).

## Release

You can create a new Ref Studio release (ex: mac `.dmg` image files) using the following:
### Remote (GitHub Action)

To release a new version use the following steps:

- update `package.json` with a new version following the [versioning](#versioning) rules.
- run the [Cut Release workflow](https://github.com/refstudio/refstudio/actions/workflows/cut-release.yml) by pressing "Run workflow" and select the branch (should be `main` or a release PR).
- open the [draft release](https://github.com/refstudio/refstudio/releases) created in the previous step
- download and test the Ref Studio application
- edit release notes to include notable changes and instalation instructions
- remove debug artifacts from the release
- publish release

### Locally

You can also create a new Ref Studio release (ex: mac `.dmg` image files) locally using the following steps:

- `yarn python` to ensure the backend python server binary is buit.
- `yarn tauri:build` to build all the supported binary files.

If you are interested only on a specific target, you should run:
Expand All @@ -170,11 +188,3 @@ If you are interested only on a specific target, you should run:
- `yarn tauri:build:mac:universal` to get a Universal macOS Binary (runs on both Apple silicon and Intel-based Macs).

After the build you can find the `.dmg` binaries in the `/binaries` folder.


### Release process (manual)

To release a new version you should update (bump) the version in the `package.json` file and run `yarn tauri:build`.
Then you should commit, and push, the version change and create a git tag with the new version released.

After that you should use the version files located in `/binaries/refstudio_{$VERSION}_{$TARGET}.dmg` (ex: `refstudio_23.1.0_universal.dmg`) and upload them to a [new GitHub release](https://github.com/refstudio/refstudio/releases/new) using the tag created.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "refstudio",
"private": true,
"version": "23.2.0-alpha.1",
"version": "23.2.0",
"description": "An open source text editor optimized for writing that relies on references.",
"type": "module",
"scripts": {
Expand Down
15 changes: 14 additions & 1 deletion python/sidecar/api.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import uvicorn
from fastapi import FastAPI

from fastapi.middleware.cors import CORSMiddleware
from sidecar.ai import router as ai_router
from sidecar.filesystem import router as filesystem_route
from sidecar.meta import router as meta_router
Expand All @@ -10,6 +10,19 @@
from sidecar.settings import router as settings_router

api = FastAPI(title="RefStudio API", version="0.1")
api.add_middleware(
CORSMiddleware,
allow_origins=[
# This for the dev server
"http://localhost:1420",
# This for the tauri desktop app (release build)
"tauri://localhost",
],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)

api.include_router(meta_router.router, prefix="/api")
api.include_router(ai_router.router, prefix="/api")
api.include_router(filesystem_route.router, prefix="/api")
Expand Down
2 changes: 1 addition & 1 deletion python/sidecar/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,4 @@

logger.addHandler(stream_handler)
logger.addHandler(file_handler)
logger.disabled = os.environ.get("SIDECAR_ENABLE_LOGGING", "false").lower() != "true"
logger.disabled = False
2 changes: 1 addition & 1 deletion python/sidecar/settings/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ def make_settings_json_path(user_id: str) -> Path:
def default_settings() -> FlatSettingsSchema:
return FlatSettingsSchema(
active_project_id="",
logging_enabled=False,
logging_enabled=True,
logging_filepath="/tmp/refstudio-sidecar.log",
model_provider=ModelProvider.OPENAI,
api_key="",
Expand Down
4 changes: 3 additions & 1 deletion src/api/typed-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { EventStreamContentType, fetchEventSource } from '@microsoft/fetch-event

import { universalDelete, universalGet, universalPatch, universalPost, universalPut } from './api';
import type { paths } from './api-paths';
import { REFSTUDIO_HOST } from './server';

type LowerMethod = 'get' | 'post' | 'put' | 'delete' | 'patch';

Expand Down Expand Up @@ -180,7 +181,8 @@ export async function apiPostStream<Path extends PathsForMethod<'post'>>(
const [options, body, onMessage] = safeArgs.length === 3 ? safeArgs : [undefined, ...safeArgs];
const path = options ? completePath(pathSpec, options) : pathSpec;

return fetchEventSource(path, {
const url = import.meta.env.VITE_IS_WEB ? path : REFSTUDIO_HOST + path;
return fetchEventSource(url, {
method: 'POST',
headers: { 'content-type': 'application/json', accept: EventStreamContentType },
openWhenHidden: false,
Expand Down
2 changes: 1 addition & 1 deletion src/application/commands/CommandPalette.css
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@
position: fixed;
top: 0;
left: 0;
z-index: 50;
width: 100vw;
height: 100vh;
user-select: none;
@apply z-modals;
@apply !bg-modal-bg-overlay;
@apply !bg-opacity-overlay;
}
Expand Down
2 changes: 0 additions & 2 deletions src/application/commands/__tests__/CommandPalette.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,6 @@ describe('CommandPalette', () => {
'Upload References',
'Search Semantic Scholar',
'New File',
'Save',
'Save File as Markdown',
'New project...',
'Open project...',
Expand Down Expand Up @@ -296,7 +295,6 @@ describe('CommandPalette', () => {
'Upload References',
'Search Semantic Scholar',
'New File',
'Save',
'Save File as Markdown',
'New project...',
'Open project...',
Expand Down
19 changes: 6 additions & 13 deletions src/application/commands/hooks/useFileCommands.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useAtomValue } from 'jotai';
import { Command } from 'kmenu';
import { VscMarkdown, VscNewFile, VscSave } from 'react-icons/vsc';
import { VscMarkdown, VscNewFile } from 'react-icons/vsc';

import { useIsEditorOpen } from '../../../atoms/hooks/useIsEditorOpen';
import { isProjectOpenAtom } from '../../../atoms/projectState';
Expand All @@ -23,18 +23,11 @@ export function useFileCommands(): Command[] {
];

if (isRefStudioEditorOpen) {
fileCommands.push(
{
icon: <VscSave />,
text: 'Save',
perform: () => emitEvent('refstudio://menu/file/save'),
},
{
icon: <VscMarkdown />,
text: 'Save File as Markdown',
perform: () => emitEvent('refstudio://menu/file/markdown'),
},
);
fileCommands.push({
icon: <VscMarkdown />,
text: 'Save File as Markdown',
perform: () => emitEvent('refstudio://menu/file/markdown'),
});
}

return [
Expand Down
2 changes: 1 addition & 1 deletion src/application/views/PdfViewer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export function PdfViewer({ file }: PdfViewerProps) {
const containerRef = useRef<HTMLDivElement>(null);
const [pdfViewerWidth, setPdfViewerWidth] = useState<number>();

const fileData = useMemo(() => ({ data: file.binaryContent }), [file]);
const fileData = useMemo(() => ({ data: Uint8Array.from(file.binaryContent) }), [file]);

// Update viewer's width on mount
useLayoutEffect(() => {
Expand Down
8 changes: 7 additions & 1 deletion src/application/views/WelcomeView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,14 @@ function WelcomeActions() {
<div className="flex flex-col items-start gap-8">
<h1 className="text-card-txt-primary">Welcome to refstudio</h1>
<div className="flex flex-col items-center gap-2 self-stretch">
<Button fluid text="New Project" onClick={() => emitEvent('refstudio://menu/file/project/new')} />
<Button
alignment="left"
fluid
text="New Project"
onClick={() => emitEvent('refstudio://menu/file/project/new')}
/>
<Button
alignment="left"
fluid
text="Try Sample Project"
type="secondary"
Expand Down
23 changes: 23 additions & 0 deletions src/atoms/chatState.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { atom } from 'jotai';

interface ChatThreadItem {
id: string;
question: string;
answer?: string;
}
export type ChatThread = ChatThreadItem[];

export const chatThreadAtom = atom<ChatThread>([]);

// {
// id: '1',
// question: 'What is your name?',
// answer:
// 'I am an AI language model and do not have a name. How may I assist you with your query related to the given context?',
// },
// {
// id: '2',
// question: 'What can you tell me about hidden feedback loops in machine learning?',
// answer:
// 'Hidden feedback loops in machine learning refer to situations where two systems indirectly influence each other through the world, leading to changes in behavior that may not be immediately visible. These loops may exist between completely disjoint systems and can make analyzing the effect of proposed changes extremely difficult, adding cost to even simple improvements. It is recommended to look carefully for hidden feedback loops and remove them whenever feasible.',
// },
8 changes: 3 additions & 5 deletions src/atoms/projectState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ import { Atom, atom } from 'jotai';
import { ProjectInfo } from '../api/projectsAPI';
import { ensureSampleProjectFiles, setCurrentFileSystemProjectId } from '../io/filesystem';
import { createModalAtoms } from './core/createModalAtoms';
import { closeAllEditorsAtom } from './editorActions';
import { refreshFileTreeAtom } from './fileExplorerActions';
import { clearAllReferencesAtom, loadReferencesAtom } from './referencesState';
import { loadReferencesAtom } from './referencesState';
import { resetStateAtom } from './resetState';

// #####################################################################################
// Internal Atoms
Expand Down Expand Up @@ -45,9 +45,7 @@ export const closeProjectAtom = atom(null, async (get, set) => {
set(currentProjectIdAtom, '');
set(currentProjectNameAtom, '');

set(closeAllEditorsAtom);
set(clearAllReferencesAtom);
await set(refreshFileTreeAtom);
await set(resetStateAtom);
}
});

Expand Down
19 changes: 19 additions & 0 deletions src/atoms/resetState.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { atom } from 'jotai';

import { chatThreadAtom } from './chatState';
import { closeAllEditorsAtom } from './editorActions';
import { refreshFileTreeAtom } from './fileExplorerActions';
import { clearAllReferencesAtom } from './referencesState';
import { selectionAtom } from './selectionState';

/**
* Reset RefStudio to initial state.
* This should be used wne the user closes the project.
*/
export const resetStateAtom = atom(null, async (_, set) => {
set(closeAllEditorsAtom);
set(clearAllReferencesAtom);
set(selectionAtom, '');
set(chatThreadAtom, []);
await set(refreshFileTreeAtom);
});
15 changes: 10 additions & 5 deletions src/components/Button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { cx } from '../lib/cx';
interface ButtonProps {
Action?: React.ReactElement;
actionPosition?: 'left' | 'right';
alignment?: 'left' | 'center';
className?: string;
disabled?: boolean;
fluid?: boolean;
Expand All @@ -19,6 +20,7 @@ interface ButtonProps {
export function Button({
Action,
actionPosition = 'left',
alignment = 'center',
className,
disabled,
fluid,
Expand All @@ -40,15 +42,18 @@ export function Button({
'w-full': fluid,
},
{
'gap-2': !size,
'justify-center gap-2 px-5 py-3': size === 'M',
'justify-center gap-1 px-[.5rem] py-[.25rem]': size === 'S',
'justify-start': alignment === 'left',
'justify-center': alignment === 'center',
},
{
'gap-2 px-5 py-3': size === 'M',
'gap-1 px-2 py-1': size === 'S',
},
{
'pl-3': !!Action && actionPosition === 'left',
'pr-3': !!Action && actionPosition === 'right',
'pl-[.25rem]': !!Action && actionPosition === 'left' && size === 'S',
'pr-[.25rem]': !!Action && actionPosition === 'right' && size === 'S',
'pl-1': !!Action && actionPosition === 'left' && size === 'S',
'pr-1 ': !!Action && actionPosition === 'right' && size === 'S',
},
{
'bg-btn-bg-primary-default text-btn-txt-primary-default': !inheritColor && type === 'primary',
Expand Down
21 changes: 17 additions & 4 deletions src/components/Checkbox.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,28 @@
import { cx } from '../lib/cx';
import { SelectedRadioIcon, UnselectedRadioIcon } from './icons';

interface RadioProps {
checked: boolean;
disabled?: boolean;
onChange: (newValue: boolean) => void;
}
export function Checkbox({ checked, onChange, ...rest }: RadioProps) {
export function Checkbox({ checked, disabled, onChange, ...rest }: RadioProps) {
return (
<div className="cursor-pointer" onClick={() => onChange(!checked)} {...rest}>
<input checked={checked} className="hidden" readOnly role="checkbox" type="checkbox" />
<div
className={cx('cursor-pointer', {
'pointer-events-none': disabled,
})}
onClick={() => onChange(!checked)}
{...rest}
>
<input checked={checked} className="hidden" disabled={disabled} readOnly role="checkbox" type="checkbox" />
{checked ? (
<div className="text-radio-active">
<div
className={cx({
'text-radio-active': !disabled,
'text-txt-muted': disabled,
})}
>
<SelectedRadioIcon />
</div>
) : (
Expand Down
Loading

0 comments on commit c31c3db

Please sign in to comment.