Commit Graph
1265 Commits
Author SHA1 Message Date
Christopher Serr d46f8b5eeb Fix Panic When Cleaning Sum of Best (#1051)
When cleaning the sum of best, the message tries to be as helpful as
possible by showing as much information about the problematic segments
as possible. Part of that is information about the date of the attempt.
However, as it turns out, the attempt may not actually exist. This
shouldn't generally happen, but we can't trust the correctness of the
splits files, so for whatever reason, the attempt may be missing. In
that case, we simply skip that information.
2025-04-15 19:17:03 +00:00
Christopher Serr d0e37b8c41 Fix Sidebar Not Refreshing in Splits Selection (#1050)
When the splits selection view is open, the sidebar and the view itself
don't refresh properly anymore when in mobile mode. This is because the
React compiler notices that with the way we wrote the code, these
components have no reason to re-render. There is currently no proper
`useMobile` hook. So while I implemented a quick workaround here, by
forcing it to not memoize the individual props properly, we should
refactor the sidebar code at some point to use a proper `useMobile`
hook.
2025-04-14 18:58:05 +00:00
Christopher Serr edc59d9062 Fix Bugs Introduced in Refactoring (#1049)
The splits selection view did not correctly cause rerenders among other
smaller bugs in there. I'm not sure how these bugs got introduced, as I
barely made changes to the content of the functions, but these were
completely different. Maybe this was Copilot's fault.

Additionally, when using Tauri, there was a bug where we had two hotkey
implementations at the same time for the pop out windows. One was the
global hotkey implementation and one was the local one we add to the pop
out window. This caused the hotkey to be triggered twice.
2025-04-13 17:11:55 +02:00
Christopher Serr 7e54e84631 Use Document Picture-in-Picture API if Available (#1047)
Chrome supports the [Document Picture-in-Picture
API](https://developer.chrome.com/blog/the-future-of-picture-in-picture/),
which allows us to create a popup window that is always on top, has a
"return to tab" button, remembers its position and size, and has a more
compact title bar. Considering not every browser supports this API, we
automatically fall back to `window.open` if the API is not available.
2025-04-12 21:38:59 +00:00
Christopher Serr a3a08bd8e6 Allow Popping Out the Timer Into a Separate Window (#1046)
This adds a new button to the sidebar that allows the user to pop out
the entire layout into a separate child window. This makes it take up
less of the screen and capture it more easily in OBS. I'm not sure if
the button should be in the sidebar or not, but it's good enough for an
initial implementation.

Changelog: You can now pop out the timer into a separate window.
2025-04-12 21:45:25 +02:00
Christopher Serr 88b874d8b2 Switch Almost Everything to Function Components (#1044)
This replaces almost all class based components with function based
components. The only exception is the top most component that handles
all the application state. That can be refactored in the future as well.
2025-04-09 20:50:37 +00:00
Christopher Serr f03689bc81 Convert Everything to CSS Modules (#1032)
This converts the remainder of the CSS files to CSS modules. The
following are not converted:
1. `variables.scss`: I'm not entirely sure if variables can be converted
   to CSS modules. The documentation states you might need PostCSS for
   it. However, we probably may want to look into CSS variables anyway.
   So this would be done in a subsequent PR.
2. `main.scss`: This declares global styles. I'm not sure if it's
   possible to convert this as this is needed from the very beginning,
   before any React is even loaded.
2025-03-31 18:42:11 +00:00
Christopher Serr 42b3c12890 Merge pull request #1030 from CryZe/reorganizing
Do some Initial Refactoring of the Code

1. This splits up the UI code into a separate views and components folder to clarify the purpose of each file.

2. This refactors some code to use CSS modules, functional React components and splits up the Settings component into roughly one component per setting.

This is just the beginning of more code refactoring.
2025-03-26 21:35:35 +01:00
Christopher Serr d771cda89d Refactor and Split Up Some Code
This refactors some code to use CSS modules, functional React components
and splits up the Settings component into roughly one component per
setting.
2025-03-26 21:18:57 +01:00
Christopher Serr 048dbf22dc Separate Views and Components 2025-03-25 22:57:15 +01:00
Christopher Serr d503c39c32 Format everything with prettier (#1029)
We didn't have Prettier until now, so this adds a configuration and
reformats everything with it.
2025-03-25 19:10:25 +00:00
Christopher Serr 456ae3b36c Add Support for Text Shadows (#1028)
This adds the ability to specify an optional text shadow in the general
layout settings.

Changelog: Text shadows are now supported and enabled by default. You
can customize the color or disable text shadows entirely in the layout
settings.
2025-03-25 17:57:22 +00:00
Christopher Serr f299a4c679 Remove splits.io Integration (#1027)
As explained [here](https://twos.dev/splitsio.html), splits.io will shut
down at the end of the month. The website is already not working
properly anymore, so it's time to remove support for it.

Changelog: [Splits.io](https://splits.io) is shutting down at the end of
the month. Integration with it has been removed.

[Ben Carlsson's Goodbye to Splits.io](https://twos.dev/splitsio.html)
2025-03-24 20:57:34 +00:00
Christopher Serr 756299f89f Switch to Lucide Icons (#1026)
We have had a really outdated version of Font Awesome directly vendored
into our repository. Not only was it outdated, but it also is shipped as
a font file, including all the icons, even though we only use a small
subset of them. By switching to Lucide, we not only are depending on
something more up to date, but now the icons can also be tree shaked.

This also updates some of our CSS to use flex box and grid instead of
manually positioning with margins.
2025-03-24 16:43:51 +00:00
Christopher Serrandaaronghiurau 2e70564bde Fix Style of Combo Boxes (#1024)
WebKit outside of Safari apparently ignores the background color of
`<select>` elements. By using `appearance: none`, we can override the
default style of the combo boxes and make them look consistent across
all browsers.

Co-authored-by: aaronghiurau <[email protected]>
2025-03-14 14:03:57 +00:00
Christopher Serr e515d366d0 Update to Tauri 2 (#1016)
This should hopefully resolve some of the issues.
2025-02-23 21:39:22 +01:00
Christopher Serr 349d95ebb0 Context Menu, CSS Modules and React 19 (#1015)
This replaces the context menu with our own. By doing that we no longer
need to force install our npm packages, as there are no longer any
conflicts. In fact, as part of this change, I updated us to the latest
React 19 and even enabled the React compiler.

I also explored CSS modules for the first time, which are going to allow
us to reduce conflicts between CSS rules and possibly even allow us to
fully remove SASS, as the need for it is going to be reduced.

I also found out that the latest Rust nightly is broken due to their
update to LLVM 20. So I pinned the version to the last working nightly
version.
2025-02-20 21:40:55 +00:00
Christopher Serr 55162c047a Implement Custom Switch (#1013)
The `react-toggle` library is unmaintained and is preventing us from
properly updating React. I already wrote a Switch for the new Auto
Splitting IDE, so I converted it once again with Copilot.
2025-02-16 14:01:16 +00:00
Christopher Serr 2fbe28e4eb Allow Invalid Color Component Inputs (#1012)
Apparently React behaves differently from Dioxus in that it doesn't
allow changing inputs if they don't affect the value that they are bound
to. So I spent some time on implementing some proper validation logic
for the color inputs.
2025-02-15 22:30:08 +00:00
Christopher Serr 759910fcd5 Implement a Custom Color Picker (#1011)
The `react-color-picker` library has been unmaintained for quite a
while and it (among other libraries) has been holding us back from
upgrading React properly. I have written a color picker for our Druid
based desktop version before and if we are going to use Dioxus for the
desktop version, I would want to port the Druid version over anyway. And
considering Dioxus is so close to React, I did just that. I ported it to
Dioxus and then let Copilot port it to React, which worked on the very
first try.
2025-02-15 21:40:30 +01:00
Christopher Serr 10eb4ec86d Turn On WebAssembly Tail Calls (#992)
With Safari 18.2 having shipped, all browsers now support WebAssembly
Tail Calls. This allows the compiler to call a function at the end of
the current function by reusing the stack frame. This should be a tiny
bit faster and allow for recursion without stack overflows... except
that Rust doesn't have any way of guaranteeing this yet, so you can't
really rely on it.
2025-02-12 21:39:18 +00:00
Christopher Serr 318ed8288f Simplify our Markdown Dependencies (#1004)
The `commonmark-react-renderer` and `react-linkifier` libraries are no
longer maintained and have held us back from upgrading our dependencies
for quite some time. This replaces the markdown rendering with an
actually maintained library: `markdown-it`.
2025-02-12 20:10:00 +01:00
Christopher Serr 51b91ac421 Update SASS (#1003)
The way importing works changed. Fortunately, they have a nice migration
tool that helped convert all the files.
2025-02-12 17:00:04 +00:00
dependabot[bot] 275ccf49ae Bump openssl from 0.10.66 to 0.10.70 in /src-tauri (#1002) 2025-02-12 16:42:10 +00:00
Christopher Serr 98719cfcfe Update eslint and Remove Unused Dependencies (#1001)
Apparently the entire configuration format changed. I didn't fully
replicate the old configuration in order to reduce the complexity of it
all, hopefully resulting in fewer maintenance headaches in the future.

Additionally, I removed some unused dependencies that were no longer
needed.
2025-02-12 16:28:42 +00:00
Christopher Serr 0d5e82c684 Disable Multivalue again (#1000)
Apparently it's currently broken again in the recent Rust nightlies, so
we have to disable it.
2025-02-11 23:52:05 +00:00
Christopher Serr ad02c3a761 Update Dependencies and Remove Tests (#997)
The tests do not work anymore. They have always been flaky and added a
lot of dependencies, that made it harder to maintain them. Additionally,
the rendering is now handled by `livesplit-core`, which has all the same
tests for the rendering, so it also makes little sense to have the same
rendering tests again in this repository. All other dependencies that
are currently updatable have been updated, except:

1. I'm not sure if you need Tauri 2 for the CLI version 2.
2. The `css-loader` causes problems with the way we import variables
   from the SASS files.
3. React 19 does not seem to just work, we get a bunch of TypeScript
   issues.
4. `commonmark` is stuck as usual until we replace it entirely.
5. `eslint` changed completely it seems, we probably need to set it up
   completely from scratch.
2025-02-12 00:09:29 +01:00
Christopher Serr ee62d69faa Don't Use WasmGC Instructions Just Yet (#990)
At some point we had to switch away from `wasm-opt` automatically
detecting the WebAssembly features, because they deprecated and turned
that into a no-op. Since then we specified that it should just use all
the features. This used to work all the time, but with the introduction
of reference types it now started optimizing some of those instructions
into instructions that are only available with the `WasmGC` proposal.
This slipped through because Chrome and Firefox already support `WasmGC`
but Safari does not... yet, because they also will start to support it
very soon. In the meantime and also to ensure `wasm-opt` isn't ever
going to sneak in any unwanted features, we now explicitly specify all
the features that we want to use.
2024-11-06 16:21:50 +00:00
Christopher Serr 663f60b7ba Switch to the web Target of wasm-bindgen (#989)
This allows us to skip letting `webpack` parse the wasm files, which
means we are not blocked by its limitations anymore. This allows us to
finally start using reference types.
2024-11-05 23:55:29 +00:00
Christopher Serr aeb016cb64 Choose Variables from Combo Boxes (#986)
Instead of manually specifying the variables via text boxes, you can now
choose them from combo boxes. This makes it easier to select the
variables you want to use for the layout.

Changelog: You can now choose variables to display on the layout from
combo boxes instead of manually specifying them via text boxes.
2024-10-27 22:02:46 +00:00
Christopher Serr 4e200e0794 Add Setting for Manual Game Time Input Mode (#985)
This allows the user to choose between specifying segment times and
split times when using the manual game timer.

Changelog: When using the **Manual Game Time Input**, you can now choose
between specifying **Segment Times** and **Split Times**.
2024-10-24 18:23:10 +00:00
Christopher Serr ca5f527b0c Merge pull request #984 from CryZe/multivalue-abi
Enable Multivalue again
2024-10-22 20:52:50 +02:00
Christopher Serr da58c85e3a Fix tests 2024-10-22 20:38:31 +02:00
Christopher Serr 2063a99b09 Enable Multivalue again
With LLVM 19 they explicitly require using the `experimental-mv` ABI in
addition to the `multivalue` LLVM feature (the latter is enabled by
default now). Enabling the ABI is non-trivial and requires a full on
custom Rust target. This adds `wasm32-multivalue.json` which is
identical to `wasm32-unknown-unknown` except it sets the
`experimental-mv` ABI. The target JSON format is very experimental by
itself, so we may need to keep this up to date from time to time.
2024-10-22 20:19:34 +02:00
dependabot[bot]anddependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> c39dbe1751 Bump openssl from 0.10.64 to 0.10.66 in /src-tauri (#955)
Bumps [openssl](https://github.com/sfackler/rust-openssl) from 0.10.64 to 0.10.66.
- [Release notes](https://github.com/sfackler/rust-openssl/releases)
- [Commits](https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.64...openssl-v0.10.66)

---
updated-dependencies:
- dependency-name: openssl
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-22 18:30:14 +00:00
Christopher Serr a44676070c Fix Desktop Build on Linux (#954)
WebAssembly needs a specific mime type to be allowed to be loaded. Tauri
by default apparently can't send headers on Linux, unless you activate a
specific feature, so the WebAssembly failed to load. Additionally,
without the dialog feature, it also wasn't able to show the error
message.
2024-07-22 15:47:37 +00:00
wooferzfgandChristopher Serr 891a972f6a Add desktop build to README (#952)
The releases were added in #951

Co-authored-by: Christopher Serr <[email protected]>
2024-07-21 17:47:40 +00:00
Christopher Serr 75f5844159 Automatically release Tauri binaries (#951)
This makes it so we automatically release the Tauri binaries when we
merge a new change to the master branch.
latest
2024-07-21 17:04:54 +00:00
Christopher Serr da502a6f9f Add Always On Top setting for Tauri (#950)
This adds support for the `Always On Top` setting in the Tauri version
of LiveSplit One. This setting allows you to keep the LiveSplit One
window on top of all other windows.
2024-07-18 00:26:04 +02:00
Christopher Serr 4c078c1feb Fix binaryen usage in CI (#949)
More CI problems :(
2024-07-17 17:44:41 +00:00
Christopher Serr 5d3ee0402c Fix CI (#948)
Turns out it's not quite right yet.
2024-07-16 21:57:14 +02:00
Christopher Serr ccb4bbd1b4 Introduce a Tauri based desktop version (#940)
This introduces a Tauri based desktop version of LiveSplit One. For now
very few changes have been done. It's mostly global hotkeys that work
now. It's unclear if Tauri is the long term solution for LiveSplit One,
but it gets us global hotkeys and auto splitting with very little
effort, so we'll use it until something better comes along.
2024-07-15 21:14:45 +02:00
Christopher Serr f6817019ab Move Server Protocol to livesplit-core (#932)
This moves the server protocol to `livesplit-core` and improves on it in
various ways:
- The protocol is based on JSON messages. This allows for example for
  more structured commands where it's easier to provide multiple
  arguments for a command and even have optional arguments.
- For each command, there is a corresponding response. It is either a
  `success` response with possibly the value that you requested, or an
  `error` response with an error `code`.
- On top of the responses you also get sent `event` messages that
  indicate changes to the timer. These can either be changes triggered
  via a command that you sent or by changes that happened through other
  sources, such as the user directly interacting with the timer or an
  auto splitter.

The protocol is still work in progress and we will evolve it into a
protocol that fully allows synchronizing timers over the network.

The event sink has now been renamed to command sink, because there is
now a clear distinction between incoming commands and events that are
the results of these commands.

Changelog: The protocol used for the server connection has been
significantly improved. There is a response for each command and clear
errors when something goes wrong. Additionally, there are now event
messages that indicate changes to the timer.
2024-06-22 13:53:26 +02:00
Christopher Serr e897dd8eff Request only a single JS bundle from index.ts (#931)
We introduce a new `indexDelayed.ts` file that bundles all the imports
that are used in the `index.ts` file. They are not imported directly
there, because we want to keep the size of the `index.html` as small as
possible, so it can focus on requesting the WASM file as soon as
possible. This should result in the `indexDelayed.ts` bundle containing
basically all the JS. This JS bundle and the WASM file should then be
requested in parallel. While it would be possible to request these all
individually over in the `index.ts`, browsers don't actually like doing
too many requests in parallel and it turns out that big JavaScript files
actually compress better than having many small ones. The WASM file also
is pretty big, so ideally we are not bottlenecked by the large JS file.
If necessary, we could do some more bundle splitting for stuff that
isn't used until much later, like the Markdown library.
2024-06-19 20:14:38 +02:00
Christopher Serr 9f3ed503ec Clean up some async race conditions & CSS fixes (#930)
The dialogs are now asynchronous as opposed to the browser built-in ones
that are synchronous, probably because they are incredibly old. The
problem with the new dialogs being asynchronous is that for example the
hotkeys, the server protocol and honestly any sort of async download
that's still running in the background can all mess with the timer while
the dialog is open. This could lead to all sorts of weird issues, like
the timer being in a different state than what the dialog expects, the
timer being reset twice and creating two dialogs that are open at the
same time and possibly even memory corruption in the Rust code.

This commit ensures that the timer can not be interacted with while it
is "locked for interaction". In fact we already had such a notion where
when you navigate to the settings, layout or run editor, the hotkeys
would be disabled. Now this is concept is extended so the event sink
also can prevent interaction with the timer. Navigating to these menus
and opening dialogs will now trigger this locking mechanism.

Additionally this improves various async race conditions in the splits
editor related to downloading resources from speedrun.com or splits.io.

This also touches the CSS of the dialogs again, adding some spacing
around the dialog, so it doesn't touch the edges of the window and
allowing the buttons to have more dynamic sizing. In particular I've
noticed that the text sometimes doesn't fit into the buttons on iOS, so
they are now allowed to grow a little to handle that situation.

File open dialogs also now know the file extensions of the files we are
looking for.
2024-06-19 19:47:08 +02:00
Christopher Serr 5b575d899f Introduce Custom Dialogs (#928)
This introduces custom dialogs to LiveSplit One. Previously we've used
the builtin browser dialogs that are very limited in what they can do.

Additionally this introduces a bunch of smaller changes:
- The splits editor is now more optimized and only searches for the game
  name whenever it or the list of games changes.
- The PWA badge now resets when the app is reloaded.
- Guests on the leaderboard can now have flags.
- If a user encounters a bug, there's now dedicated toast popups that
  don't disappear and direct the user to the issue tracker.
- The Sum of Best cleaner now ensures the run can't be modified while
  the cleaning is in progress, which would lead to memory corruption,
  especially with the async nature of the new dialogs.
- Cancelling out of opening files doesn't lead to an error anymore.

The following changes are introduced by updating `livesplit-core`:
- When resizing images / reencoding them as PNG, we now use a higher
  compression setting.
- Invalid timer states are not unrepresentable anymore.
2024-06-18 21:33:54 +02:00
Christopher Serr 3b32a7b085 Add a fallback for the time tracking in the web (#814) (#927)
Every browser's `performance.now()` implementation is not spec
compliant, unless the browser is running on Windows. On every other
operating system, `performance.now()` does not properly keep ticking
while the operating system is suspended / sleeping. There isn't much
that we can do. What we can do is we calculate the initial difference
between `performance.now()` and `Date.now()` and store it in a thread
local. Later, when the phone gets locked, `performance.now()` starts to
break. However, we can detect when the phone gets unlocked again by
listening to the `visibilitychange` event. This is where we can update
the difference again. This of course isn't ideal, as `Date.now()` gets
adjusted by NTP synchronizations, but it's the best we can do.

More information:
https://developer.mozilla.org/en-US/docs/Web/API/Performance/now#ticking_during_sleep
https://www.igvita.com/2015/11/20/dont-lose-user-and-app-state-use-page-visibility/
2024-06-09 23:38:41 +02:00
Christopher Serr ba45f1759c Dynamically adjust the column widths (#926)
Instead of assuming each column has the width of the text `88:88:88`, we
now determine the largest string per column (based on unicode scalar
values) and adjust the column width accordingly. There is still a fixed
minimum width based on the string `88:88`, which ensures that the
columns don't switch sizes too often, especially if you start with empty
splits. We could've also chosen `8:88:88`, which would ensure there's no
column size change as you approach the hour mark. However, this would
increase the size of delta columns unnecessarily. So it's a little bit
of a trade-off.
2024-06-09 18:05:53 +02:00
Christopher Serr 97c741c5db Make the PWA Icon maskable (#925)
Even though we added the margin, some Android devices still need it to
be maskable to properly understand the margin.
2024-06-09 17:33:37 +02:00
Christopher Serr 5ff3d171a2 Enable the WebAssembly Multivalue feature (#924)
This enables the multivalue feature when building with the nightly Rust
compiler. This is because the Rust standard library is not built with
the multivalue feature enabled by default. Also we need to specifically
use the spec compliant C ABI for it to work, which is also nightly only.
2024-06-08 22:56:52 +02:00