Skip to content

Commit

Permalink
SMM2->3 migration modal, new user modal, disk space warning, markdown…
Browse files Browse the repository at this point in the history
… format annoucements (#224)
  • Loading branch information
budak7273 authored Sep 13, 2024
1 parent 35e7fc2 commit 9f4dd03
Show file tree
Hide file tree
Showing 14 changed files with 444 additions and 14 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
Mod manager for [Satisfactory](https://www.satisfactorygame.com/).
Handles all the steps of installing mods for you.

Implemented in [Wails](https://wails.io/).
Implemented in [Wails](https://wails.io/) using [Svelte](https://svelte.dev/) and [Skeleton](https://www.skeleton.dev/).

## Installation and Usage

Expand Down
59 changes: 59 additions & 0 deletions backend/migration/migration.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package migration

import (
"errors"
"fmt"
"log/slog"
"os"
"path/filepath"

"github.com/spf13/viper"
)

type migration struct {
smm2Dir string
migrationSuccessMarkerPath string
}

var Migration *migration

func Init() {
if Migration == nil {
Migration = &migration{}
Migration.smm2Dir = filepath.Join(viper.GetString("smm-local-dir"), "profiles")
Migration.migrationSuccessMarkerPath = filepath.Join(Migration.smm2Dir, migrationSuccessMarkerFile)
}
}

const migrationSuccessMarkerFile = ".smm3_migration_acknowledged"

// https://stackoverflow.com/questions/12518876/how-to-check-if-a-file-exists-in-go
func pathExists(path string) bool {
if _, err := os.Stat(path); err == nil {
return true
} else if errors.Is(err, os.ErrNotExist) {
return false
} else {
slog.Warn("Error when checking path exists, so assuming it does not exist: "+path, slog.Any("error", err))
return false
}
}

func (m *migration) NeedsSmm2Migration() bool {
if pathExists(m.smm2Dir) {
return !pathExists(Migration.migrationSuccessMarkerPath)
}
return false
}

func (m *migration) MarkSmm2MigrationSuccess() error {
file, err := os.Create(Migration.migrationSuccessMarkerPath)
if err != nil {
return fmt.Errorf("failed to create migration success marker file: %w", err)
}
err = file.Close()
if err != nil {
return fmt.Errorf("failed to close file: %w", err)
}
return nil
}
30 changes: 30 additions & 0 deletions backend/settings/settings.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"os"
"path/filepath"

psUtilDisk "github.com/shirou/gopsutil/v3/disk"
"github.com/spf13/viper"
wailsRuntime "github.com/wailsapp/wails/v2/pkg/runtime"

Expand Down Expand Up @@ -65,6 +66,8 @@ type settings struct {
CacheDir string `json:"cacheDir,omitempty"`

Debug bool `json:"debug,omitempty"`

NewUserSetupComplete bool `json:"newUserSetupComplete,omitempty"`
}

var Settings = &settings{
Expand Down Expand Up @@ -95,6 +98,18 @@ var Settings = &settings{
LaunchButton: "normal",

Debug: false,

NewUserSetupComplete: false,
}

func (s *settings) GetNewUserSetupComplete() bool {
return s.NewUserSetupComplete
}

func (s *settings) SetNewUserSetupComplete(value bool) {
slog.Info("changing NewUserSetupComplete state", slog.Bool("value", value))
s.NewUserSetupComplete = value
_ = SaveSettings()
}

func (s *settings) FavoriteMod(modReference string) (bool, error) {
Expand Down Expand Up @@ -314,6 +329,21 @@ func ValidateCacheDir(dir string) error {
return nil
}

// GetCacheDirDiskSpaceLeft returns the amount of disk space left on the cache directory's disk in bytes
func (s *settings) GetCacheDirDiskSpaceLeft() (uint64, error) {
cacheDir := s.GetCacheDir()
err := ValidateCacheDir(cacheDir)
if err != nil {
return 0, fmt.Errorf("cache directory to check space on failed to validate: %w", err)
}

usage, err := psUtilDisk.Usage(cacheDir)
if err != nil {
return 0, fmt.Errorf("failed to get disk free space: %w", err)
}
return usage.Free, nil
}

func moveCacheDir(newDir string) error {
if newDir == viper.GetString("cache-dir") {
return nil
Expand Down
1 change: 1 addition & 0 deletions cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
"Maximised",
"Minimised",
"mircearoata",
"noclose",
"Nyan",
"smmanager",
"smmprofile",
Expand Down
47 changes: 44 additions & 3 deletions frontend/src/App.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@
import ErrorDetails from '$lib/components/modals/ErrorDetails.svelte';
import ErrorModal from '$lib/components/modals/ErrorModal.svelte';
import ExternalInstallMod from '$lib/components/modals/ExternalInstallMod.svelte';
import MigrationModal from '$lib/components/modals/MigrationModal.svelte';
import { supportedProgressTypes } from '$lib/components/modals/ProgressModal.svelte';
import FirstTimeSetupModal from '$lib/components/modals/first-time-setup/FirstTimeSetupModal.svelte';
import { modalRegistry } from '$lib/components/modals/modalsRegistry';
import ImportProfile from '$lib/components/modals/profiles/ImportProfile.svelte';
import { isUpdateOnStart } from '$lib/components/modals/smmUpdate/smmUpdate';
Expand All @@ -23,9 +25,11 @@
import { getModalStore, initializeModalStore } from '$lib/skeletonExtensions';
import { installs, invalidInstalls, progress } from '$lib/store/ficsitCLIStore';
import { error, expandedMod, siteURL } from '$lib/store/generalStore';
import { konami, language, updateCheckMode } from '$lib/store/settingsStore';
import { cacheDir, konami, language, updateCheckMode } from '$lib/store/settingsStore';
import { smmUpdate, smmUpdateReady } from '$lib/store/smmUpdateStore';
import { ExpandMod, UnexpandMod } from '$wailsjs/go/app/app';
import { NeedsSmm2Migration } from '$wailsjs/go/migration/migration';
import { GetCacheDirDiskSpaceLeft, GetNewUserSetupComplete } from '$wailsjs/go/settings/settings';
import { Environment, EventsOn } from '$wailsjs/runtime';
initializeStores();
Expand Down Expand Up @@ -138,11 +142,19 @@
meta: {
persistent: true,
},
});
});
}
}
}
$: GetCacheDirDiskSpaceLeft().then((spaceLeftBytes) => {
if (spaceLeftBytes < 10e9) {
const spaceLeftGbReadable = (spaceLeftBytes * 1e-9).toFixed(1);
$error = `The drive your cache directory is on (${$cacheDir}) is very low on disk space (Only ~${spaceLeftGbReadable} GB left). Please free up some space or move the cache directory to another drive in the Mod Manager Settings.`;
}
}).catch((err) => {
$error = `failed to check cache directory disk space left: ${err}`;
});
$: if ($smmUpdateReady && $updateCheckMode === 'ask') {
modalStore.trigger({
type: 'component',
Expand All @@ -163,6 +175,35 @@
$error = null;
}
// Order of checks is intentional
NeedsSmm2Migration().then((needsMigration) => {
if (needsMigration) {
modalStore.trigger({
type: 'component',
component: {
ref: MigrationModal,
},
meta: {
persistent: true,
},
});
}
}).then(() => {
GetNewUserSetupComplete().then((wasSetupCompleted) => {
if (!wasSetupCompleted) {
modalStore.trigger({
type: 'component',
component: {
ref: FirstTimeSetupModal,
},
meta: {
persistent: true,
},
});
}
});
});
EventsOn('externalInstallMod', (modReference: string, version: string) => {
if (!modReference) return;
modalStore.trigger({
Expand Down
7 changes: 7 additions & 0 deletions frontend/src/_global.postcss
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,13 @@ button {
}
}

.announcement-markdown-content {
& a {
@apply text-yellow-500;
text-decoration: underline;
}
}

.markdown-content {
@apply text-base;

Expand Down
10 changes: 8 additions & 2 deletions frontend/src/lib/components/announcements/Announcement.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import SvgIcon from '$lib/components/SVGIcon.svelte';
import { type Announcement, AnnouncementImportance } from '$lib/generated';
import { viewedAnnouncements } from '$lib/store/settingsStore';
import { markdown as renderMarkdown } from '$lib/utils/markdown';
export let announcement: Pick<Announcement, 'id' | 'importance' | 'message'>;
Expand All @@ -20,14 +21,19 @@
return mdiInformationOutline;
}
})();
$: rendered = renderMarkdown(announcement.message);
</script>

<div class="announcement-{importanceLower} announcement-bg p-1.5 h-full" class:announcement-new={isNew}>
<div class="flex items-center announcement-bg-text p-1 h-full">
<SvgIcon class="w-8 h-8 mr-3 shrink-0" icon={icon} />
<div class="grow wrap text-lg">
<slot>
{announcement.message}
<div class="announcement-markdown-content">
<!-- eslint-disable-next-line svelte/no-at-html-tags -->
{@html rendered}
</div>
</slot>
</div>
</div>
Expand Down Expand Up @@ -77,4 +83,4 @@
.announcement-new.announcement-bg {
animation: slide 6s linear infinite;
}
</style>
</style>
18 changes: 13 additions & 5 deletions frontend/src/lib/components/announcements/AnnouncementsBar.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import { AnnouncementImportance, type Announcement as AnnouncementType, GetAnnouncementsDocument, SmrHealthcheckDocument } from '$lib/generated';
import { type PopupSettings, popup } from '$lib/skeletonExtensions';
import { offline, viewedAnnouncements } from '$lib/store/settingsStore';
import { markdown as renderMarkdown } from '$lib/utils/markdown';
import { SetAnnouncementViewed } from '$wailsjs/go/settings/settings';
const { t } = getTranslate();
Expand Down Expand Up @@ -118,16 +119,23 @@
},
placement: 'bottom',
} satisfies PopupSettings;
$: renderedTooltip = (() => {
const content = $offline ? offlineAnnouncement.message : announcements[currentIndex]?.message;
if (content?.length > 0) {
return renderMarkdown(content);
}
return content;
})();
</script>

<!-- the if gets executed before this is added to the DOM for some reason if this is below the ifs, so the use:popup would not find the element -->
<Tooltip disabled={!$offline && !announcements[currentIndex]} {popupId}>
<span>
{#if $offline}
{offlineAnnouncement.message}
{:else}
{announcements[currentIndex]?.message}
{/if}
<div class="announcement-markdown-content">
<!-- eslint-disable-next-line svelte/no-at-html-tags -->
{@html renderedTooltip}
</div>
</span>
</Tooltip>

Expand Down
4 changes: 3 additions & 1 deletion frontend/src/lib/components/left-bar/LeftBar.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -364,7 +364,9 @@
</button>
</div>
<div class="flex flex-col gap-2">
<span class="pl-4 sticky top-0 z-[1] bg-surface-50-900-token">Links</span>
<span class="pl-4 sticky top-0 z-[1] bg-surface-50-900-token">
<T defaultValue="Links" keyName="left-bar.links"/>
</span>
<button
class="btn w-full bg-surface-200-700-token px-4 h-8 text-sm"
on:click={() => BrowserOpenURL($siteURL)}>
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/lib/components/left-bar/Settings.svelte
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<script lang="ts">
import { mdiBug, mdiCheck, mdiCheckboxBlankOutline, mdiCheckboxMarkedOutline, mdiChevronRight, mdiClipboard, mdiCog, mdiDownload, mdiFolderEdit, mdiLanConnect, mdiTune } from '@mdi/js';
import { mdiBug, mdiCheck, mdiCheckboxBlankOutline, mdiCheckboxMarkedOutline, mdiChevronRight, mdiClipboard, mdiCog, mdiDownload, mdiEggEaster, mdiFolderEdit, mdiLanConnect, mdiTune } from '@mdi/js';
import { ListBox, ListBoxItem } from '@skeletonlabs/skeleton';
import { getTranslate } from '@tolgee/svelte';
import { getContextClient } from '@urql/svelte';
Expand Down Expand Up @@ -465,7 +465,7 @@
{#if $konami}
<hr class="divider" />
<li class="section-header">
<span class="h-5 w-5"><SvgIcon class="h-full w-full" icon={mdiCog}/></span>
<span class="h-5 w-5"><SvgIcon class="h-full w-full" icon={mdiEggEaster}/></span>
<span class="flex-auto">
<T defaultValue="Secret settings" keyName="settings.secret-settings"/>
</span>
Expand Down
Loading

0 comments on commit 9f4dd03

Please sign in to comment.