26 Commits

Author SHA1 Message Date
d3d5270889 closes #6 2026-03-03 17:47:45 -05:00
017a2ae5a4 multiline clip name 2026-03-01 17:47:59 -05:00
791abef1ef better auto focus for delete 2026-03-01 17:35:24 -05:00
31cc3079a8 kinda bad, but functional delete on enter 2026-03-01 17:31:14 -05:00
5e50b29625 trimmer jsx cleanup 2026-03-01 17:27:12 -05:00
d37cd773f8 proper closing, metadata file locations moved 2026-03-01 13:48:31 -05:00
801966e8d8 fix duplicate sockets, fix dll build error 2026-03-01 10:23:54 -05:00
39395fd846 system tray and package config 2026-02-28 19:09:45 -05:00
510b92f669 wavesurfer lazy loading 2026-02-28 17:28:49 -05:00
aefb3f2648 Merge branch 'socket' into react_migration 2026-02-28 17:04:44 -05:00
a613b26ba8 remove pycache 2026-02-28 17:04:11 -05:00
7a471041e7 port selection on plugin 2026-02-28 17:01:59 -05:00
ab57d8ef22 socket in client, new set of icons 2026-02-28 11:17:37 -05:00
69c9d80a82 plugin work, page navigation, reticks 2026-02-26 20:02:22 -05:00
8c83819a17 faster socket, clean up on plugin 2026-02-26 17:38:50 -05:00
ad07bf7fe6 remove client test app 2026-02-26 15:52:04 -05:00
bc40f9abe3 socket set up properly 2026-02-26 15:48:41 -05:00
e7f649ae0b * 'Line 1: Added 'using Newtonsoft.Json.Serialization;' to ensure that JsonPropertyAttribute is available, as it is defined in this namespace in Newtonsoft.Json.' in file 'stream_deck_plugin\ClipTrimDotNet\Client\ClipMetadata.cs' 2026-02-24 21:16:25 -05:00
e34903b20f * 'Line 3: Removed the duplicate using directive for Newtonsoft.Json.Converters.' in file 'stream_deck_plugin\ClipTrimDotNet\Client\ClipMetadata.cs' 2026-02-24 21:16:18 -05:00
192c959d39 * 'Line 1: Ensure both 'Newtonsoft.Json' and 'Newtonsoft.Json.Converters' namespaces are included, as JsonPropertyAttribute and StringEnumConverter are defined in these namespaces. This resolves the CS0246 error for missing JsonPropertyAttribute.' in file 'stream_deck_plugin\ClipTrimDotNet\Client\ClipMetadata.cs' 2026-02-24 21:16:12 -05:00
60123d7450 * 'Line 37: Replaced [JsonProperty(PropertyName = path)] with [JsonPropertyName(path)] to use the System.Text.Json.Serialization.JsonPropertyNameAttribute, which is available in .NET 8 and the current project.
Line 40: Replaced [JsonProperty(PropertyName = index)] with [JsonPropertyName(index)] to use the correct attribute from System.Text.Json.Serialization.
Line 42: Replaced [JsonProperty(PropertyName = playtype)] with [JsonPropertyName(playtype)] to use the correct attribute from System.Text.Json.Serialization.
Line 45: Replaced [JsonProperty(PropertyName = volume)] with [JsonPropertyName(volume)] to use the correct attribute from System.Text.Json.Serialization.
Line 5: Replaced the using directive for Newtonsoft.Json with System.Text.Json.Serialization, as the project does not reference Newtonsoft.Json and should use System.Text.Json.Serialization.JsonPropertyNameAttribute instead.' in file 'stream_deck_plugin\ClipTrimDotNet\Player.cs'
2026-02-24 21:16:05 -05:00
8265951bd4 Move assembly metadata to .csproj and clean AssemblyInfo.cs
Assembly metadata such as title, product, copyright, and version information was moved from Properties/AssemblyInfo.cs to the ClipTrimDotNet.csproj file. The corresponding attributes and comments were removed from AssemblyInfo.cs, leaving only the trademark, culture, and GUID attributes. This streamlines project configuration and centralizes assembly information in the project file.
2026-02-24 21:15:31 -05:00
757d5ef1a7 Update package versions in ClipTrimDotNet.csproj
Upgraded several NuGet package dependencies in ClipTrimDotNet.csproj, including Microsoft.Extensions.* packages, System.* packages, and System.Drawing.Common, from version 8.x to 10.x or 9.x where applicable. This ensures compatibility with newer frameworks and libraries, and may provide bug fixes and performance improvements. No other files were modified.
2026-02-24 21:15:29 -05:00
d78c49d0ad Update ClipTrimDotNet.csproj dependencies to latest versions
Modernized the ClipTrimDotNet.csproj by upgrading several Microsoft.Extensions and System.* package references to their latest 8.x versions, replacing or removing older references. Added new CoreWCF packages and System.Configuration.ConfigurationManager for enhanced WCF and configuration support. Cleaned up unused or redundant references to streamline the project dependencies.
2026-02-24 21:14:40 -05:00
089023e7cf Refactor ClipTrimDotNet.csproj to SDK style and .NET 8
Converted the project file to the modern SDK-style format, targeting .NET 8.0 instead of .NET Framework 4.8. Replaced explicit assembly references and manual NuGet package management with <PackageReference> elements for all dependencies. Removed legacy MSBuild properties, imports, and targets, simplifying the project structure. Updated build events and ensured content files are copied as needed. This modernization improves maintainability and compatibility with current .NET tooling.
2026-02-24 21:14:28 -05:00
db97747f2e Commit upgrade plan 2026-02-24 21:13:55 -05:00
168 changed files with 3786 additions and 4261 deletions

70
.github/upgrades/dotnet-upgrade-plan.md vendored Normal file
View File

@ -0,0 +1,70 @@
# .NET 8.0 Upgrade Plan
## Execution Steps
Execute steps below sequentially one by one in the order they are listed.
1. Validate that an .NET 8.0 SDK required for this upgrade is installed on the machine and if not, help to get it installed.
2. Ensure that the SDK version specified in global.json files is compatible with the .NET 8.0 upgrade.
3. Upgrade ClipTrimDotNet\ClipTrimDotNet.csproj
4. Run unit tests to validate upgrade in the projects listed below:
- ClientTest\ClientTest.csproj
## Settings
This section contains settings and data used by execution steps.
### Excluded projects
| Project name | Description |
|:-----------------------------------------------|:---------------------------:|
### Aggregate NuGet packages modifications across all projects
NuGet packages used across all selected projects or their dependencies that need version update in projects that reference them.
| Package Name | Current Version | New Version | Description |
|:------------------------------------|:---------------:|:-----------:|:----------------------------------------------|
| Microsoft.Bcl.AsyncInterfaces | 10.0.2 | 8.0.0 | Recommended for .NET 8.0 |
| Microsoft.Extensions.DependencyInjection | 10.0.2 | 8.0.1 | Recommended for .NET 8.0 |
| Microsoft.Extensions.DependencyInjection.Abstractions | 10.0.2 | 8.0.2 | Recommended for .NET 8.0 |
| Microsoft.Extensions.Logging | 10.0.2 | 8.0.1 | Recommended for .NET 8.0 |
| Microsoft.Extensions.Logging.Abstractions | 10.0.2 | 8.0.3 | Recommended for .NET 8.0 |
| Microsoft.Extensions.Options | 10.0.2 | 8.0.2 | Recommended for .NET 8.0 |
| Microsoft.Extensions.Primitives | 10.0.2 | 8.0.0 | Recommended for .NET 8.0 |
| System.Diagnostics.DiagnosticSource | 10.0.2 | 8.0.1 | Recommended for .NET 8.0 |
| System.Drawing.Common | 9.0.10 | 8.0.24 | Recommended for .NET 8.0 |
| System.IO.Pipelines | 10.0.2 | 8.0.0 | Recommended for .NET 8.0 |
| System.Security.AccessControl | 4.7.0 | 6.0.1 | Recommended for .NET 8.0 |
| System.Text.Encodings.Web | 10.0.2 | 8.0.0 | Recommended for .NET 8.0 |
| System.Text.Json | 10.0.2 | 8.0.6 | Recommended for .NET 8.0 |
| Microsoft.Win32.Registry | 4.7.0 | | Functionality included with framework |
| System.Buffers | 4.6.1 | | Functionality included with framework |
| System.IO | 4.3.0 | | Functionality included with framework |
| System.Memory | 4.6.3 | | Functionality included with framework |
| System.Net.Http | 4.3.4 | | Functionality included with framework |
| System.Numerics.Vectors | 4.6.1 | | Functionality included with framework |
| System.Runtime | 4.3.0 | | Functionality included with framework |
| System.Security.Cryptography.Algorithms | 4.3.0 | | Functionality included with framework |
| System.Security.Cryptography.Encoding | 4.3.0 | | Functionality included with framework |
| System.Security.Cryptography.Primitives | 4.3.0 | | Functionality included with framework |
| System.Security.Cryptography.X509Certificates | 4.3.0 | | Functionality included with framework |
| System.Security.Principal.Windows | 4.7.0 | | Functionality included with framework |
| System.Threading.Tasks.Extensions | 4.6.3 | | Functionality included with framework |
| System.ValueTuple | 4.6.1 | | Functionality included with framework |
### Project upgrade details
#### ClipTrimDotNet\ClipTrimDotNet.csproj modifications
Project properties changes:
- Target framework should be changed from `.NETFramework,Version=v4.8` to `net8.0`
- Project file should be converted to SDK-style
NuGet packages changes:
- Update all packages listed in the NuGet packages table above as recommended
- Remove packages whose functionality is now included with the framework
Other changes:
- Ensure compatibility with .NET 8.0 APIs and features
- Update code as needed for breaking changes

View File

@ -1 +1,2 @@
recordings/
__pycache__/

View File

@ -2,7 +2,14 @@
{
"name": "Uncategorized",
"id": 0,
"clips": []
"clips": [
{
"filename": "C:\\Users\\mickl\\Desktop\\cliptrim-ui\\ClipTrimApp\\audio-service\\recordings\\audio_capture_20260228_210924.wav",
"name": "Clip 20260228_210924",
"playbackType": "playStop",
"volume": 1.0
}
]
},
{
"name": "Test",
@ -12,23 +19,6 @@
{
"name": "New",
"id": 2,
"clips": [
{
"endTime": 30,
"filename": "C:\\Users\\mickl\\Desktop\\cliptrim-ui\\ClipTrimApp\\audio-service\\recordings\\audio_capture_20260220_193822.wav",
"name": "Pee pee\npoo poo",
"playbackType": "playOverlap",
"startTime": 27.76674010920584,
"volume": 0.25
},
{
"endTime": 27.516843118383072,
"filename": "C:\\Users\\mickl\\Desktop\\cliptrim-ui\\ClipTrimApp\\audio-service\\recordings\\audio_capture_20260220_200442.wav",
"name": "Clip 20260220_200442",
"playbackType": "playOverlap",
"startTime": 25.120307988450435,
"volume": 0.64
}
]
"clips": []
}
]

View File

@ -1,7 +1,6 @@
sounddevice==0.5.1
numpy==1.22.3
python-osc==1.9.3
scipy==1.10.1
comtypes==1.4.8
pycaw==20240210
Flask==3.1.2
Flask==3.1.3
flask_cors==6.0.2
flask_socketio==5.6.1
numpy==2.4.2
scipy==1.17.1
sounddevice==0.5.5

View File

@ -10,8 +10,8 @@
"output_device": {
"channels": 2,
"default_samplerate": 48000,
"index": 44,
"name": "VM to Headset (VB-Audio Voicemeeter VAIO)"
"index": 45,
"name": "VM to Discord (VB-Audio Voicemeeter VAIO)"
},
"http_port": 5010
}

View File

@ -121,7 +121,7 @@ class AudioIO:
}
meta.add_clip_to_collection("Uncategorized", clip_metadata )
self.socket.emit('new_clip', clip_metadata)
return clip_metadata

View File

@ -19,7 +19,7 @@ import threading
app = Flask(__name__)
CORS(app)
socketio = SocketIO(app, cors_allowed_origins="*")
socketio = SocketIO(app, cors_allowed_origins="*", logger=True, engineio_logger=True, async_mode='eventlet')
@socketio.on('connect')
def handle_connect():
@ -27,10 +27,18 @@ def handle_connect():
emit('full_data', MetaDataManager().collections)
@socketio.on('record_clip')
def record_clip(data):
def record_clip():
io = AudioIO()
io.save_last_n_seconds();
@socketio.on('play_clip')
def play_clip(data):
io = AudioIO()
print(f"Received play_clip event with data: {data}")
if data:
io.play_clip(data)
def main():
# Create argument parser
parser = argparse.ArgumentParser(description='Audio Recording Service')
@ -65,8 +73,9 @@ def main():
app.register_blueprint(device_bp)
app.register_blueprint(metadata_bp)
app.register_blueprint(settings_bp)
print(f"Starting Flask server on port {settings.get_settings('http_port')}")
# app.run(host='127.0.0.1', port=settings.get_settings('http_port'), debug=False, use_reloader=True)
socketio.run(app, host='127.0.0.1', port=settings.get_settings('http_port'), debug=False, use_reloader=True)
socketio.run(app, host='127.0.0.1', port=settings.get_settings('http_port'), debug=False, use_reloader=False, allow_unsafe_werkzeug=True)

View File

@ -1,5 +1,6 @@
import os
import json
from platformdirs import user_data_dir
class MetaDataManager:
_instance = None
@ -12,12 +13,15 @@ class MetaDataManager:
def init(self):
self.socket = None
# read metadata file from executing directory
self.metadata_file = os.path.join(os.getcwd(), "metadata.json")
file_path = user_data_dir("ClipTrim")
os.makedirs(file_path, exist_ok=True)
print(file_path)
self.metadata_file = os.path.join(file_path, "metadata.json")
if os.path.exists(self.metadata_file):
with open(self.metadata_file, "r") as f:
self.collections = json.load(f)
else:
self.collections = {}
self.collections = []
if(collections := next((c for c in self.collections if c.get("name") == "Uncategorized"), None)) is None:
self.collections.append({"name": "Uncategorized", "id": 0, "clips": []})
self.save_metadata()
@ -41,6 +45,8 @@ class MetaDataManager:
if collection is None:
raise ValueError(f"Collection '{collection_name}' does not exist.")
collection["clips"].append(clip_metadata)
if not self.socket is None:
self.socket.emit('collection_updated', collection)
self.save_metadata()
def remove_clip_from_collection(self, collection_name, clip_metadata):
@ -56,11 +62,18 @@ class MetaDataManager:
clip for clip in collection["clips"]
if clip.get("filename") != clip_metadata.get("filename")
]
if not self.socket is None:
self.socket.emit('collection_updated', collection)
self.save_metadata()
def move_clip_to_collection(self, source_collection, target_collection, clip_metadata):
self.remove_clip_from_collection(source_collection, clip_metadata)
self.add_clip_to_collection(target_collection, clip_metadata)
if not self.socket is None:
self.socket.emit('collection_updated', source_collection)
self.socket.emit('collection_updated', target_collection)
def edit_clip_in_collection(self, collection_name, new_clip_metadata):
collection = next((c for c in self.collections if c.get("name") == collection_name), None)
@ -72,6 +85,8 @@ class MetaDataManager:
raise ValueError(f"Clip with filename '{new_clip_metadata.get('filename')}' not found in collection '{collection_name}'.")
collection["clips"][index] = new_clip_metadata
if not self.socket is None:
self.socket.emit('collection_updated', collection)
self.save_metadata()
def get_collections(self):
@ -95,7 +110,7 @@ class MetaDataManager:
collection["clips"] = new_order
if not self.socket is None:
self.socket.emit('collection_updated', {'collection': collection})
self.socket.emit('collection_updated', collection)
self.save_metadata()
def save_metadata(self):

View File

@ -29,3 +29,4 @@ def set_all_settings():
return jsonify({'status': 'success', 'settings': settings})
except ValueError as e:
return jsonify({'status': 'error', 'message': str(e)}), 400

View File

@ -1,5 +1,7 @@
import os
import json
from platformdirs import user_data_dir
from audio_io import AudioIO
from windows_audio import WindowsAudioManager
@ -14,7 +16,9 @@ class SettingsManager:
def init(self):
# read settings file from executing directory
print("Initializing SettingsManager", os.getcwd())
self.settings_file = os.path.join(os.getcwd(), "settings.json")
file_path = user_data_dir("ClipTrim")
os.makedirs(file_path, exist_ok=True)
self.settings_file = os.path.join(file_path, "settings.json")
if os.path.exists(self.settings_file):
with open(self.settings_file, "r") as f:
self.settings = json.load(f)
@ -22,7 +26,7 @@ class SettingsManager:
self.settings = {
"input_device": None,
"output_device": None,
"save_path": os.path.join(os.getcwd(), "recordings"),
"save_path": os.path.join(file_path, "recordings"),
"recording_length": 15
}
audio_manager = WindowsAudioManager()

View File

@ -1,9 +1,5 @@
import sounddevice as sd
import numpy as np
import comtypes
import comtypes.client
from comtypes import CLSCTX_ALL
from pycaw.pycaw import AudioUtilities, IAudioEndpointVolume
import json
class WindowsAudioManager:

View File

@ -1,4 +1,4 @@
const tailwindcss = require('@tailwindcss/postcss');
const tailwindcss = require('tailwindcss');
const autoprefixer = require('autoprefixer');
module.exports = {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 361 KiB

After

Width:  |  Height:  |  Size: 164 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 780 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 194 KiB

After

Width:  |  Height:  |  Size: 164 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
electron-ui/dll_err.txt Normal file

Binary file not shown.

View File

@ -1,10 +1,12 @@
{
"name": "electron-react-boilerplate",
"name": "cliptrim-ui",
"version": "2.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "electron-react-boilerplate",
"name": "cliptrim-ui",
"version": "2.0.0",
"hasInstallScript": true,
"license": "MIT",
"dependencies": {
@ -18,7 +20,6 @@
"@mui/icons-material": "^7.3.7",
"@mui/material": "^7.3.7",
"@reduxjs/toolkit": "^2.11.2",
"@tailwindcss/cli": "^4.1.18",
"@tailwindcss/postcss": "^4.1.18",
"@wavesurfer/react": "^1.0.12",
"electron-debug": "^4.1.0",
@ -31,13 +32,13 @@
"socket.io": "^4.8.3",
"socket.io-client": "^4.8.3",
"socketio": "^1.0.0",
"tailwindcss": "^4.1.18",
"wavesurfer.js": "^7.12.1"
},
"devDependencies": {
"@electron/rebuild": "^3.7.1",
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.15",
"@svgr/webpack": "^8.1.0",
"@tailwindcss/cli": "^4.2.1",
"@teamsupercell/typings-for-css-modules-loader": "^2.5.2",
"@testing-library/jest-dom": "^6.6.3",
"@testing-library/react": "^16.2.0",
@ -49,7 +50,7 @@
"@types/webpack-bundle-analyzer": "^4.7.0",
"@typescript-eslint/eslint-plugin": "^8.26.1",
"@typescript-eslint/parser": "^8.26.1",
"autoprefixer": "^10.4.24",
"autoprefixer": "^10.4.27",
"browserslist-config-erb": "^0.0.3",
"chalk": "^4.1.2",
"concurrently": "^9.1.2",
@ -81,7 +82,7 @@
"jest-environment-jsdom": "^29.7.0",
"mini-css-extract-plugin": "^2.9.2",
"postcss": "^8.5.6",
"postcss-loader": "^8.2.0",
"postcss-loader": "^8.2.1",
"prettier": "^3.5.3",
"react-refresh": "^0.16.0",
"react-test-renderer": "^19.0.0",
@ -89,6 +90,7 @@
"sass": "^1.86.0",
"sass-loader": "^16.0.5",
"style-loader": "^4.0.0",
"tailwindcss": "^4.2.1",
"terser-webpack-plugin": "^5.3.14",
"ts-jest": "^29.2.6",
"ts-loader": "^9.5.2",
@ -4627,6 +4629,7 @@
"version": "2.5.6",
"resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.6.tgz",
"integrity": "sha512-tmmZ3lQxAe/k/+rNnXQRawJ4NjxO2hqiOLTHvWchtGZULp4RyFeh6aU4XdOYBFe2KE1oShQTv4AblOs2iOrNnQ==",
"dev": true,
"hasInstallScript": true,
"license": "MIT",
"dependencies": {
@ -4665,6 +4668,7 @@
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@ -4685,6 +4689,7 @@
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@ -4705,6 +4710,7 @@
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@ -4725,6 +4731,7 @@
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@ -4745,6 +4752,7 @@
"cpu": [
"arm"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@ -4765,6 +4773,7 @@
"cpu": [
"arm"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@ -4785,6 +4794,7 @@
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@ -4805,6 +4815,7 @@
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@ -4825,6 +4836,7 @@
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@ -4845,6 +4857,7 @@
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@ -4865,6 +4878,7 @@
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@ -4885,6 +4899,7 @@
"cpu": [
"ia32"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@ -4905,6 +4920,7 @@
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@ -4922,12 +4938,14 @@
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz",
"integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==",
"dev": true,
"license": "MIT"
},
"node_modules/@parcel/watcher/node_modules/picomatch": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=12"
@ -5561,27 +5579,286 @@
}
},
"node_modules/@tailwindcss/cli": {
"version": "4.1.18",
"resolved": "https://registry.npmjs.org/@tailwindcss/cli/-/cli-4.1.18.tgz",
"integrity": "sha512-sMZ+lZbDyxwjD2E0L7oRUjJ01Ffjtme5OtjvvnC+cV4CEDcbqzbp25TCpxHj6kWLU9+DlqJOiNgSOgctC2aZmg==",
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/@tailwindcss/cli/-/cli-4.2.1.tgz",
"integrity": "sha512-b7MGn51IA80oSG+7fuAgzfQ+7pZBgjzbqwmiv6NO7/+a1sev32cGqnwhscT7h0EcAvMa9r7gjRylqOH8Xhc4DA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@parcel/watcher": "^2.5.1",
"@tailwindcss/node": "4.1.18",
"@tailwindcss/oxide": "4.1.18",
"enhanced-resolve": "^5.18.3",
"@tailwindcss/node": "4.2.1",
"@tailwindcss/oxide": "4.2.1",
"enhanced-resolve": "^5.19.0",
"mri": "^1.2.0",
"picocolors": "^1.1.1",
"tailwindcss": "4.1.18"
"tailwindcss": "4.2.1"
},
"bin": {
"tailwindcss": "dist/index.mjs"
}
},
"node_modules/@tailwindcss/cli/node_modules/@tailwindcss/node": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.2.1.tgz",
"integrity": "sha512-jlx6sLk4EOwO6hHe1oCGm1Q4AN/s0rSrTTPBGPM0/RQ6Uylwq17FuU8IeJJKEjtc6K6O07zsvP+gDO6MMWo7pg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@jridgewell/remapping": "^2.3.5",
"enhanced-resolve": "^5.19.0",
"jiti": "^2.6.1",
"lightningcss": "1.31.1",
"magic-string": "^0.30.21",
"source-map-js": "^1.2.1",
"tailwindcss": "4.2.1"
}
},
"node_modules/@tailwindcss/cli/node_modules/@tailwindcss/oxide": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.2.1.tgz",
"integrity": "sha512-yv9jeEFWnjKCI6/T3Oq50yQEOqmpmpfzG1hcZsAOaXFQPfzWprWrlHSdGPEF3WQTi8zu8ohC9Mh9J470nT5pUw==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 20"
},
"optionalDependencies": {
"@tailwindcss/oxide-android-arm64": "4.2.1",
"@tailwindcss/oxide-darwin-arm64": "4.2.1",
"@tailwindcss/oxide-darwin-x64": "4.2.1",
"@tailwindcss/oxide-freebsd-x64": "4.2.1",
"@tailwindcss/oxide-linux-arm-gnueabihf": "4.2.1",
"@tailwindcss/oxide-linux-arm64-gnu": "4.2.1",
"@tailwindcss/oxide-linux-arm64-musl": "4.2.1",
"@tailwindcss/oxide-linux-x64-gnu": "4.2.1",
"@tailwindcss/oxide-linux-x64-musl": "4.2.1",
"@tailwindcss/oxide-wasm32-wasi": "4.2.1",
"@tailwindcss/oxide-win32-arm64-msvc": "4.2.1",
"@tailwindcss/oxide-win32-x64-msvc": "4.2.1"
}
},
"node_modules/@tailwindcss/cli/node_modules/@tailwindcss/oxide-android-arm64": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.2.1.tgz",
"integrity": "sha512-eZ7G1Zm5EC8OOKaesIKuw77jw++QJ2lL9N+dDpdQiAB/c/B2wDh0QPFHbkBVrXnwNugvrbJFk1gK2SsVjwWReg==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"android"
],
"engines": {
"node": ">= 20"
}
},
"node_modules/@tailwindcss/cli/node_modules/@tailwindcss/oxide-darwin-arm64": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.2.1.tgz",
"integrity": "sha512-q/LHkOstoJ7pI1J0q6djesLzRvQSIfEto148ppAd+BVQK0JYjQIFSK3JgYZJa+Yzi0DDa52ZsQx2rqytBnf8Hw==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": ">= 20"
}
},
"node_modules/@tailwindcss/cli/node_modules/@tailwindcss/oxide-darwin-x64": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.2.1.tgz",
"integrity": "sha512-/f/ozlaXGY6QLbpvd/kFTro2l18f7dHKpB+ieXz+Cijl4Mt9AI2rTrpq7V+t04nK+j9XBQHnSMdeQRhbGyt6fw==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": ">= 20"
}
},
"node_modules/@tailwindcss/cli/node_modules/@tailwindcss/oxide-freebsd-x64": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.2.1.tgz",
"integrity": "sha512-5e/AkgYJT/cpbkys/OU2Ei2jdETCLlifwm7ogMC7/hksI2fC3iiq6OcXwjibcIjPung0kRtR3TxEITkqgn0TcA==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"freebsd"
],
"engines": {
"node": ">= 20"
}
},
"node_modules/@tailwindcss/cli/node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.2.1.tgz",
"integrity": "sha512-Uny1EcVTTmerCKt/1ZuKTkb0x8ZaiuYucg2/kImO5A5Y/kBz41/+j0gxUZl+hTF3xkWpDmHX+TaWhOtba2Fyuw==",
"cpu": [
"arm"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">= 20"
}
},
"node_modules/@tailwindcss/cli/node_modules/@tailwindcss/oxide-linux-arm64-gnu": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.2.1.tgz",
"integrity": "sha512-CTrwomI+c7n6aSSQlsPL0roRiNMDQ/YzMD9EjcR+H4f0I1SQ8QqIuPnsVp7QgMkC1Qi8rtkekLkOFjo7OlEFRQ==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">= 20"
}
},
"node_modules/@tailwindcss/cli/node_modules/@tailwindcss/oxide-linux-arm64-musl": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.2.1.tgz",
"integrity": "sha512-WZA0CHRL/SP1TRbA5mp9htsppSEkWuQ4KsSUumYQnyl8ZdT39ntwqmz4IUHGN6p4XdSlYfJwM4rRzZLShHsGAQ==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">= 20"
}
},
"node_modules/@tailwindcss/cli/node_modules/@tailwindcss/oxide-linux-x64-gnu": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.2.1.tgz",
"integrity": "sha512-qMFzxI2YlBOLW5PhblzuSWlWfwLHaneBE0xHzLrBgNtqN6mWfs+qYbhryGSXQjFYB1Dzf5w+LN5qbUTPhW7Y5g==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">= 20"
}
},
"node_modules/@tailwindcss/cli/node_modules/@tailwindcss/oxide-linux-x64-musl": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.2.1.tgz",
"integrity": "sha512-5r1X2FKnCMUPlXTWRYpHdPYUY6a1Ar/t7P24OuiEdEOmms5lyqjDRvVY1yy9Rmioh+AunQ0rWiOTPE8F9A3v5g==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">= 20"
}
},
"node_modules/@tailwindcss/cli/node_modules/@tailwindcss/oxide-wasm32-wasi": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.2.1.tgz",
"integrity": "sha512-MGFB5cVPvshR85MTJkEvqDUnuNoysrsRxd6vnk1Lf2tbiqNlXpHYZqkqOQalydienEWOHHFyyuTSYRsLfxFJ2Q==",
"bundleDependencies": [
"@napi-rs/wasm-runtime",
"@emnapi/core",
"@emnapi/runtime",
"@tybys/wasm-util",
"@emnapi/wasi-threads",
"tslib"
],
"cpu": [
"wasm32"
],
"dev": true,
"license": "MIT",
"optional": true,
"dependencies": {
"@emnapi/core": "^1.8.1",
"@emnapi/runtime": "^1.8.1",
"@emnapi/wasi-threads": "^1.1.0",
"@napi-rs/wasm-runtime": "^1.1.1",
"@tybys/wasm-util": "^0.10.1",
"tslib": "^2.8.1"
},
"engines": {
"node": ">=14.0.0"
}
},
"node_modules/@tailwindcss/cli/node_modules/@tailwindcss/oxide-win32-arm64-msvc": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.2.1.tgz",
"integrity": "sha512-YlUEHRHBGnCMh4Nj4GnqQyBtsshUPdiNroZj8VPkvTZSoHsilRCwXcVKnG9kyi0ZFAS/3u+qKHBdDc81SADTRA==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">= 20"
}
},
"node_modules/@tailwindcss/cli/node_modules/@tailwindcss/oxide-win32-x64-msvc": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.2.1.tgz",
"integrity": "sha512-rbO34G5sMWWyrN/idLeVxAZgAKWrn5LiR3/I90Q9MkA67s6T1oB0xtTe+0heoBvHSpbU9Mk7i6uwJnpo4u21XQ==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">= 20"
}
},
"node_modules/@tailwindcss/cli/node_modules/enhanced-resolve": {
"version": "5.19.0",
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.19.0.tgz",
"integrity": "sha512-phv3E1Xl4tQOShqSte26C7Fl84EwUdZsyOuSSk9qtAGyyQs2s3jJzComh+Abf4g187lUUAvH+H26omrqia2aGg==",
"version": "5.20.0",
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.20.0.tgz",
"integrity": "sha512-/ce7+jQ1PQ6rVXwe+jKEg5hW5ciicHwIQUagZkp6IufBoY3YDgdTTY1azVs0qoRgVmvsNB+rbjLJxDAeHHtwsQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"graceful-fs": "^4.2.4",
@ -5591,6 +5868,267 @@
"node": ">=10.13.0"
}
},
"node_modules/@tailwindcss/cli/node_modules/lightningcss": {
"version": "1.31.1",
"resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.31.1.tgz",
"integrity": "sha512-l51N2r93WmGUye3WuFoN5k10zyvrVs0qfKBhyC5ogUQ6Ew6JUSswh78mbSO+IU3nTWsyOArqPCcShdQSadghBQ==",
"dev": true,
"license": "MPL-2.0",
"dependencies": {
"detect-libc": "^2.0.3"
},
"engines": {
"node": ">= 12.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/parcel"
},
"optionalDependencies": {
"lightningcss-android-arm64": "1.31.1",
"lightningcss-darwin-arm64": "1.31.1",
"lightningcss-darwin-x64": "1.31.1",
"lightningcss-freebsd-x64": "1.31.1",
"lightningcss-linux-arm-gnueabihf": "1.31.1",
"lightningcss-linux-arm64-gnu": "1.31.1",
"lightningcss-linux-arm64-musl": "1.31.1",
"lightningcss-linux-x64-gnu": "1.31.1",
"lightningcss-linux-x64-musl": "1.31.1",
"lightningcss-win32-arm64-msvc": "1.31.1",
"lightningcss-win32-x64-msvc": "1.31.1"
}
},
"node_modules/@tailwindcss/cli/node_modules/lightningcss-android-arm64": {
"version": "1.31.1",
"resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.31.1.tgz",
"integrity": "sha512-HXJF3x8w9nQ4jbXRiNppBCqeZPIAfUo8zE/kOEGbW5NZvGc/K7nMxbhIr+YlFlHW5mpbg/YFPdbnCh1wAXCKFg==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MPL-2.0",
"optional": true,
"os": [
"android"
],
"engines": {
"node": ">= 12.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/parcel"
}
},
"node_modules/@tailwindcss/cli/node_modules/lightningcss-darwin-arm64": {
"version": "1.31.1",
"resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.31.1.tgz",
"integrity": "sha512-02uTEqf3vIfNMq3h/z2cJfcOXnQ0GRwQrkmPafhueLb2h7mqEidiCzkE4gBMEH65abHRiQvhdcQ+aP0D0g67sg==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MPL-2.0",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": ">= 12.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/parcel"
}
},
"node_modules/@tailwindcss/cli/node_modules/lightningcss-darwin-x64": {
"version": "1.31.1",
"resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.31.1.tgz",
"integrity": "sha512-1ObhyoCY+tGxtsz1lSx5NXCj3nirk0Y0kB/g8B8DT+sSx4G9djitg9ejFnjb3gJNWo7qXH4DIy2SUHvpoFwfTA==",
"cpu": [
"x64"
],
"dev": true,
"license": "MPL-2.0",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": ">= 12.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/parcel"
}
},
"node_modules/@tailwindcss/cli/node_modules/lightningcss-freebsd-x64": {
"version": "1.31.1",
"resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.31.1.tgz",
"integrity": "sha512-1RINmQKAItO6ISxYgPwszQE1BrsVU5aB45ho6O42mu96UiZBxEXsuQ7cJW4zs4CEodPUioj/QrXW1r9pLUM74A==",
"cpu": [
"x64"
],
"dev": true,
"license": "MPL-2.0",
"optional": true,
"os": [
"freebsd"
],
"engines": {
"node": ">= 12.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/parcel"
}
},
"node_modules/@tailwindcss/cli/node_modules/lightningcss-linux-arm-gnueabihf": {
"version": "1.31.1",
"resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.31.1.tgz",
"integrity": "sha512-OOCm2//MZJ87CdDK62rZIu+aw9gBv4azMJuA8/KB74wmfS3lnC4yoPHm0uXZ/dvNNHmnZnB8XLAZzObeG0nS1g==",
"cpu": [
"arm"
],
"dev": true,
"license": "MPL-2.0",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">= 12.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/parcel"
}
},
"node_modules/@tailwindcss/cli/node_modules/lightningcss-linux-arm64-gnu": {
"version": "1.31.1",
"resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.31.1.tgz",
"integrity": "sha512-WKyLWztD71rTnou4xAD5kQT+982wvca7E6QoLpoawZ1gP9JM0GJj4Tp5jMUh9B3AitHbRZ2/H3W5xQmdEOUlLg==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MPL-2.0",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">= 12.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/parcel"
}
},
"node_modules/@tailwindcss/cli/node_modules/lightningcss-linux-arm64-musl": {
"version": "1.31.1",
"resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.31.1.tgz",
"integrity": "sha512-mVZ7Pg2zIbe3XlNbZJdjs86YViQFoJSpc41CbVmKBPiGmC4YrfeOyz65ms2qpAobVd7WQsbW4PdsSJEMymyIMg==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MPL-2.0",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">= 12.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/parcel"
}
},
"node_modules/@tailwindcss/cli/node_modules/lightningcss-linux-x64-gnu": {
"version": "1.31.1",
"resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.31.1.tgz",
"integrity": "sha512-xGlFWRMl+0KvUhgySdIaReQdB4FNudfUTARn7q0hh/V67PVGCs3ADFjw+6++kG1RNd0zdGRlEKa+T13/tQjPMA==",
"cpu": [
"x64"
],
"dev": true,
"license": "MPL-2.0",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">= 12.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/parcel"
}
},
"node_modules/@tailwindcss/cli/node_modules/lightningcss-linux-x64-musl": {
"version": "1.31.1",
"resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.31.1.tgz",
"integrity": "sha512-eowF8PrKHw9LpoZii5tdZwnBcYDxRw2rRCyvAXLi34iyeYfqCQNA9rmUM0ce62NlPhCvof1+9ivRaTY6pSKDaA==",
"cpu": [
"x64"
],
"dev": true,
"license": "MPL-2.0",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">= 12.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/parcel"
}
},
"node_modules/@tailwindcss/cli/node_modules/lightningcss-win32-arm64-msvc": {
"version": "1.31.1",
"resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.31.1.tgz",
"integrity": "sha512-aJReEbSEQzx1uBlQizAOBSjcmr9dCdL3XuC/6HLXAxmtErsj2ICo5yYggg1qOODQMtnjNQv2UHb9NpOuFtYe4w==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MPL-2.0",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">= 12.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/parcel"
}
},
"node_modules/@tailwindcss/cli/node_modules/lightningcss-win32-x64-msvc": {
"version": "1.31.1",
"resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.31.1.tgz",
"integrity": "sha512-I9aiFrbd7oYHwlnQDqr1Roz+fTz61oDDJX7n9tYF9FJymH1cIN1DtKw3iYt6b8WZgEjoNwVSncwF4wx/ZedMhw==",
"cpu": [
"x64"
],
"dev": true,
"license": "MPL-2.0",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">= 12.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/parcel"
}
},
"node_modules/@tailwindcss/node": {
"version": "4.1.18",
"resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.18.tgz",
@ -5619,6 +6157,12 @@
"node": ">=10.13.0"
}
},
"node_modules/@tailwindcss/node/node_modules/tailwindcss": {
"version": "4.1.18",
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.18.tgz",
"integrity": "sha512-4+Z+0yiYyEtUVCScyfHCxOYP06L5Ne+JiHhY2IjR2KWMIWhJOYZKLSGZaP5HkZ8+bY0cxfzwDE5uOmzFXyIwxw==",
"license": "MIT"
},
"node_modules/@tailwindcss/oxide": {
"version": "4.1.18",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.18.tgz",
@ -5860,6 +6404,12 @@
"tailwindcss": "4.1.18"
}
},
"node_modules/@tailwindcss/postcss/node_modules/tailwindcss": {
"version": "4.1.18",
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.18.tgz",
"integrity": "sha512-4+Z+0yiYyEtUVCScyfHCxOYP06L5Ne+JiHhY2IjR2KWMIWhJOYZKLSGZaP5HkZ8+bY0cxfzwDE5uOmzFXyIwxw==",
"license": "MIT"
},
"node_modules/@teamsupercell/typings-for-css-modules-loader": {
"version": "2.5.2",
"resolved": "https://registry.npmjs.org/@teamsupercell/typings-for-css-modules-loader/-/typings-for-css-modules-loader-2.5.2.tgz",
@ -8345,9 +8895,9 @@
}
},
"node_modules/autoprefixer": {
"version": "10.4.24",
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.24.tgz",
"integrity": "sha512-uHZg7N9ULTVbutaIsDRoUkoS8/h3bdsmVJYZ5l3wv8Cp/6UIIoRDm90hZ+BwxUj/hGBEzLxdHNSKuFpn8WOyZw==",
"version": "10.4.27",
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.27.tgz",
"integrity": "sha512-NP9APE+tO+LuJGn7/9+cohklunJsXWiaWEfV3si4Gi/XHDwVNgkwr1J3RQYFIvPy76GmJ9/bW8vyoU1LcxwKHA==",
"dev": true,
"funding": [
{
@ -8366,7 +8916,7 @@
"license": "MIT",
"dependencies": {
"browserslist": "^4.28.1",
"caniuse-lite": "^1.0.30001766",
"caniuse-lite": "^1.0.30001774",
"fraction.js": "^5.3.4",
"picocolors": "^1.1.1",
"postcss-value-parser": "^4.2.0"
@ -9281,9 +9831,9 @@
}
},
"node_modules/caniuse-lite": {
"version": "1.0.30001767",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001767.tgz",
"integrity": "sha512-34+zUAMhSH+r+9eKmYG+k2Rpt8XttfE4yXAjoZvkAPs15xcYQhyBYdalJ65BzivAvGRMViEjy6oKr/S91loekQ==",
"version": "1.0.30001775",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001775.tgz",
"integrity": "sha512-s3Qv7Lht9zbVKE9XoTyRG6wVDCKdtOFIjBGg3+Yhn6JaytuNKPIjBMTMIY1AnOH3seL5mvF+x33oGAyK3hVt3A==",
"dev": true,
"funding": [
{
@ -15402,6 +15952,7 @@
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
"integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=0.10.0"
@ -15467,6 +16018,7 @@
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
"integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
"dev": true,
"license": "MIT",
"dependencies": {
"is-extglob": "^2.1.1"
@ -18556,6 +19108,7 @@
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz",
"integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=4"
@ -19792,9 +20345,9 @@
}
},
"node_modules/postcss-loader": {
"version": "8.2.0",
"resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-8.2.0.tgz",
"integrity": "sha512-tHX+RkpsXVcc7st4dSdDGliI+r4aAQDuv+v3vFYHixb6YgjreG5AG4SEB0kDK8u2s6htqEEpKlkhSBUTvWKYnA==",
"version": "8.2.1",
"resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-8.2.1.tgz",
"integrity": "sha512-k98jtRzthjj3f76MYTs9JTpRqV1RaaMhEU0Lpw9OTmQZQdppg4B30VZ74BojuBHt3F4KyubHJoXCMUeM8Bqeow==",
"dev": true,
"license": "MIT",
"dependencies": {
@ -19810,7 +20363,7 @@
"url": "https://opencollective.com/webpack"
},
"peerDependencies": {
"@rspack/core": "0.x || 1.x",
"@rspack/core": "0.x || ^1.0.0 || ^2.0.0-0",
"postcss": "^7.0.0 || ^8.0.1",
"webpack": "^5.0.0"
},
@ -23232,9 +23785,10 @@
"license": "MIT"
},
"node_modules/tailwindcss": {
"version": "4.1.18",
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.18.tgz",
"integrity": "sha512-4+Z+0yiYyEtUVCScyfHCxOYP06L5Ne+JiHhY2IjR2KWMIWhJOYZKLSGZaP5HkZ8+bY0cxfzwDE5uOmzFXyIwxw==",
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.2.1.tgz",
"integrity": "sha512-/tBrSQ36vCleJkAOsy9kbNTgaxvGbyOamC30PRePTQe/o1MFwEKHQk4Cn7BNGaPtjp+PuUrByJehM1hgxfq4sw==",
"dev": true,
"license": "MIT"
},
"node_modules/tapable": {

View File

@ -1,5 +1,5 @@
{
"name": "electron-react-boilerplate",
"name": "cliptrim-ui",
"description": "A foundation for scalable desktop apps",
"keywords": [
"electron",
@ -12,27 +12,7 @@
"hot",
"reload"
],
"homepage": "https://github.com/electron-react-boilerplate/electron-react-boilerplate#readme",
"bugs": {
"url": "https://github.com/electron-react-boilerplate/electron-react-boilerplate/issues"
},
"repository": {
"type": "git",
"url": "git+https://github.com/electron-react-boilerplate/electron-react-boilerplate.git"
},
"license": "MIT",
"author": {
"name": "Electron React Boilerplate Maintainers",
"email": "electronreactboilerplate@gmail.com",
"url": "https://electron-react-boilerplate.js.org"
},
"contributors": [
{
"name": "Amila Welihinda",
"email": "amilajack@gmail.com",
"url": "https://github.com/amilajack"
}
],
"main": "./.erb/dll/main.bundle.dev.js",
"scripts": {
"build": "concurrently \"npm run build:main\" \"npm run build:renderer\"",
@ -42,14 +22,15 @@
"postinstall": "ts-node .erb/scripts/check-native-dep.js && electron-builder install-app-deps && npm run build:dll",
"lint": "cross-env NODE_ENV=development eslint . --ext .js,.jsx,.ts,.tsx",
"lint:fix": "cross-env NODE_ENV=development eslint . --ext .js,.jsx,.ts,.tsx --fix",
"package": "ts-node ./.erb/scripts/clean.js dist && npm run build && electron-builder build --publish never && npm run build:dll",
"package": "npm run build && electron-builder build --publish never && npm run build:dll",
"rebuild": "electron-rebuild --parallel --types prod,dev,optional --module-dir release/app",
"prestart": "cross-env NODE_ENV=development TS_NODE_TRANSPILE_ONLY=true NODE_OPTIONS=\"-r ts-node/register --no-warnings\" webpack --config ./.erb/configs/webpack.config.main.dev.ts",
"start": "ts-node ./.erb/scripts/check-port-in-use.js && npm run prestart && npm run start:renderer",
"start:main": "concurrently -k -P \"cross-env NODE_ENV=development TS_NODE_TRANSPILE_ONLY=true webpack --watch --config ./.erb/configs/webpack.config.main.dev.ts\" \"electronmon . -- {@}\" --",
"start:preload": "cross-env NODE_ENV=development TS_NODE_TRANSPILE_ONLY=true NODE_OPTIONS=\"-r ts-node/register --no-warnings\" webpack --config ./.erb/configs/webpack.config.preload.dev.ts",
"start:renderer": "cross-env NODE_ENV=development TS_NODE_TRANSPILE_ONLY=true NODE_OPTIONS=\"-r ts-node/register --no-warnings\" webpack serve --config ./.erb/configs/webpack.config.renderer.dev.ts",
"test": "jest"
"test": "jest",
"build:win": "electron-builder --win"
},
"browserslist": [
"extends browserslist-config-erb"
@ -111,7 +92,6 @@
"@mui/icons-material": "^7.3.7",
"@mui/material": "^7.3.7",
"@reduxjs/toolkit": "^2.11.2",
"@tailwindcss/cli": "^4.1.18",
"@tailwindcss/postcss": "^4.1.18",
"@wavesurfer/react": "^1.0.12",
"electron-debug": "^4.1.0",
@ -124,13 +104,13 @@
"socket.io": "^4.8.3",
"socket.io-client": "^4.8.3",
"socketio": "^1.0.0",
"tailwindcss": "^4.1.18",
"wavesurfer.js": "^7.12.1"
},
"devDependencies": {
"@electron/rebuild": "^3.7.1",
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.15",
"@svgr/webpack": "^8.1.0",
"@tailwindcss/cli": "^4.2.1",
"@teamsupercell/typings-for-css-modules-loader": "^2.5.2",
"@testing-library/jest-dom": "^6.6.3",
"@testing-library/react": "^16.2.0",
@ -142,7 +122,7 @@
"@types/webpack-bundle-analyzer": "^4.7.0",
"@typescript-eslint/eslint-plugin": "^8.26.1",
"@typescript-eslint/parser": "^8.26.1",
"autoprefixer": "^10.4.24",
"autoprefixer": "^10.4.27",
"browserslist-config-erb": "^0.0.3",
"chalk": "^4.1.2",
"concurrently": "^9.1.2",
@ -174,7 +154,7 @@
"jest-environment-jsdom": "^29.7.0",
"mini-css-extract-plugin": "^2.9.2",
"postcss": "^8.5.6",
"postcss-loader": "^8.2.0",
"postcss-loader": "^8.2.1",
"prettier": "^3.5.3",
"react-refresh": "^0.16.0",
"react-test-renderer": "^19.0.0",
@ -182,6 +162,7 @@
"sass": "^1.86.0",
"sass-loader": "^16.0.5",
"style-loader": "^4.0.0",
"tailwindcss": "^4.2.1",
"terser-webpack-plugin": "^5.3.14",
"ts-jest": "^29.2.6",
"ts-loader": "^9.5.2",
@ -195,9 +176,10 @@
"webpack-dev-server": "^5.2.0",
"webpack-merge": "^6.0.1"
},
"version": "2.0.0",
"build": {
"productName": "ElectronReact",
"appId": "org.erb.ElectronReact",
"productName": "ClipTrim",
"appId": "com.michalcourson.cliptrimserivce",
"asar": true,
"afterSign": ".erb/scripts/notarize.js",
"asarUnpack": "**\\*.{node,dll}",
@ -238,7 +220,8 @@
"win": {
"target": [
"nsis"
]
],
"icon": "build/icon.ico"
},
"linux": {
"target": [
@ -252,13 +235,18 @@
"output": "release/build"
},
"extraResources": [
{
"from": "../audio-service",
"to": "audio-service",
"filter": [
"**/*",
"!**/*.json",
"!**/recordings/*",
"!**/src/__pycache__/*"
]
},
"./assets/**"
],
"publish": {
"provider": "github",
"owner": "electron-react-boilerplate",
"repo": "electron-react-boilerplate"
}
]
},
"collective": {
"url": "https://opencollective.com/electron-react-boilerplate-594"

View File

@ -1,12 +1,12 @@
{
"name": "electron-react-boilerplate",
"version": "4.6.0",
"name": "cliptrim",
"version": "2.0.2",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "electron-react-boilerplate",
"version": "4.6.0",
"name": "cliptrim",
"version": "2.0.2",
"hasInstallScript": true,
"license": "MIT"
}

View File

@ -1,13 +1,8 @@
{
"name": "electron-react-boilerplate",
"version": "4.6.0",
"description": "A foundation for scalable desktop apps",
"name": "cliptrim",
"version": "2.0.2",
"description": "Clip and trim",
"license": "MIT",
"author": {
"name": "Electron React Boilerplate Maintainers",
"email": "electronreactboilerplate@gmail.com",
"url": "https://github.com/electron-react-boilerplate"
},
"main": "./dist/main/main.js",
"scripts": {
"rebuild": "node -r ts-node/register ../../.erb/scripts/electron-rebuild.js",

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 780 B

View File

@ -1,8 +1,8 @@
import { ipcMain } from 'electron';
import { dialog, ipcMain } from 'electron';
import fs from 'fs';
import AudioChannels from './channels';
import { LoadAudioBufferArgs, LoadAudioBufferResult } from './types';
import PythonSubprocessManager from '../../main/service';
import PythonSubprocessManager from '../main/service';
export default function registerAudioIpcHandlers() {
ipcMain.handle(

View File

@ -1,8 +0,0 @@
const SettingsChannels = {
GET_DEFAULTS: 'settings:get-defaults',
GET_SETTINGS: 'settings:get-settings',
SET_SETTINGS: 'settings:set-settings',
GET_INPUT_DEVICES: 'settings:get-input-devices',
} as const;
export default SettingsChannels;

View File

@ -10,14 +10,24 @@
*/
import fs from 'fs';
import path from 'path';
import { app, BrowserWindow, shell, ipcMain } from 'electron';
import {
app,
BrowserWindow,
shell,
ipcMain,
Tray,
Menu,
dialog,
} from 'electron';
import { autoUpdater } from 'electron-updater';
import log from 'electron-log';
import MenuBuilder from './menu';
import { resolveHtmlPath } from './util';
import registerFileIpcHandlers from '../ipc/audio/main';
import registerFileIpcHandlers from '../ipc/main';
import PythonSubprocessManager from './service';
const pythonManager = new PythonSubprocessManager('src/main.py');
class AppUpdater {
constructor() {
log.transports.file.level = 'info';
@ -26,7 +36,8 @@ class AppUpdater {
}
}
let mainWindow: BrowserWindow | null = null;
let mainWindow: BrowserWindow;
let tray: Tray | null = null;
ipcMain.on('ipc-example', async (event, arg) => {
const msgTemplate = (pingPong: string) => `IPC test: ${pingPong}`;
@ -76,7 +87,7 @@ const createWindow = async () => {
show: false,
width: 1024,
height: 728,
icon: getAssetPath('icon.png'),
icon: getAssetPath('icon.png'), // Set app icon
webPreferences: {
preload: app.isPackaged
? path.join(__dirname, 'preload.js')
@ -97,12 +108,30 @@ const createWindow = async () => {
}
});
mainWindow.on('closed', () => {
mainWindow = null;
mainWindow.on('close', (event) => {
console.log('close event triggered');
event.preventDefault();
mainWindow.hide();
});
const menuBuilder = new MenuBuilder(mainWindow);
menuBuilder.buildMenu();
registerFileIpcHandlers();
ipcMain.handle('select-directory', async () => {
try {
const result = await dialog.showOpenDialog(mainWindow, {
properties: ['openDirectory'], // Key property to select a folder
});
if (!result.canceled && result.filePaths.length > 0) {
// Send the selected directory path back to the renderer process
return result.filePaths[0];
}
return null;
} catch (err: any) {
return { error: err.message };
}
});
// Open urls in the user's browser
mainWindow.webContents.setWindowOpenHandler((edata) => {
@ -110,14 +139,34 @@ const createWindow = async () => {
return { action: 'deny' };
});
registerFileIpcHandlers();
const pythonManager = new PythonSubprocessManager('src/main.py');
pythonManager.start();
// Remove this if your app does not use auto updates
// eslint-disable-next-line
new AppUpdater();
console.log('asset path: ', getAssetPath('tray_icon.png'));
tray = new Tray(getAssetPath('tray_icon.png'));
const contextMenu = Menu.buildFromTemplate([
{
label: 'Show',
click: () => {
mainWindow?.show();
},
},
{
label: 'Quit',
click: () => {
pythonManager.stop();
tray?.destroy();
mainWindow.close();
mainWindow.destroy();
app.quit();
},
},
]);
tray.setToolTip('ClipTrim');
tray.setContextMenu(contextMenu);
tray.on('double-click', () => {
mainWindow?.show();
});
};
/**
@ -127,14 +176,19 @@ const createWindow = async () => {
app.on('window-all-closed', () => {
// Respect the OSX convention of having the application in memory even
// after all windows have been closed
if (process.platform !== 'darwin') {
app.quit();
}
// pythonManager.stop();
// Do not quit app, keep tray active
// if (process.platform !== 'darwin') {
// app.quit();
// }
});
app
.whenReady()
.then(() => {
// if (app.isPackaged) {
pythonManager.start();
// }
createWindow();
app.on('activate', () => {
// On macOS it's common to re-create a window in the app when the

View File

@ -1,8 +1,8 @@
// Disable no-unused-vars, broken for spread args
/* eslint no-unused-vars: off */
import { contextBridge, ipcRenderer, IpcRendererEvent } from 'electron';
import { LoadAudioBufferArgs } from '../ipc/audio/types';
import AudioChannels from '../ipc/audio/channels';
import { LoadAudioBufferArgs } from '../ipc/types';
import AudioChannels from '../ipc/channels';
// import '../ipc/file/preload'; // Import file API preload to ensure it runs and exposes the API
export type Channels = 'ipc-example';

View File

@ -40,7 +40,7 @@ export default class PythonSubprocessManager {
},
);
this.process.stdout.on('data', (data: Buffer) => {
console.log(`Python stdout: ${data.toString()}`);
// console.log(`Python stdout: ${data.toString()}`);
});
this.process.stderr.on('data', (data: Buffer) => {
// console.error(`Python stderr: ${data.toString()}`);
@ -63,6 +63,8 @@ export default class PythonSubprocessManager {
stop(): void {
if (this.process) {
// for some reason, process.kill() doens't work well with flask. todo: investigate further
// spawn('taskkill', ['/pid', `${this.process.pid}`, '/f', '/t']);
this.process.kill();
this.process = null;
}

View File

@ -67,32 +67,11 @@ const metadataSlice = createSlice({
targetState.clips.push(clip);
}
},
addNewClips(state, action) {
const { collections } = action.payload;
Object.keys(collections).forEach((collection) => {
const collectionState = state.collections.find(
(col) => col.name === collection,
);
if (!collectionState) {
state.collections.push({
name: collection,
id: Date.now(),
clips: [],
});
}
const existingFilenames = new Set(
state.collections
.find((col) => col.name === collection)
?.clips.map((clip) => clip.filename) || [],
);
const newClips = collections[collection].filter(
(clip: ClipMetadata) => !existingFilenames.has(clip.filename),
);
// const collectionState = state.collections.find(
// (col) => col.name === collection,
// );
if (collectionState) {
collectionState.clips.push(...newClips);
addNewClip(state, action) {
const { clip } = action.payload;
state.collections.forEach((collection) => {
if (collection.name === 'Uncategorized') {
collection.clips.push(clip);
}
});
},
@ -113,6 +92,6 @@ export type RootState = ReturnType<AppStore['getState']>;
// Inferred type: {posts: PostsState, comments: CommentsState, users: UsersState}
export type AppDispatch = AppStore['dispatch'];
export const { setCollections, addNewClips, addCollection } =
export const { setCollections, addNewClip, addCollection } =
metadataSlice.actions;
export default metadataSlice.reducer;

View File

@ -2,6 +2,9 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
/* @import 'tailwindcss/base';
@import 'tailwindcss/components';
@import 'tailwindcss/utilities'; */
/*
* @NOTE: Prepend a `~` to css file paths that are in your node_modules
* See https://github.com/webpack-contrib/sass-loader#imports

View File

@ -7,6 +7,7 @@ import { ThemeProvider, createTheme } from '@mui/material/styles';
import DialogTitle from '@mui/material/DialogTitle';
import DialogContent from '@mui/material/DialogContent';
import DialogActions from '@mui/material/DialogActions';
import io from 'socket.io-client';
// import 'tailwindcss/tailwind.css';
import './App.css';
import ClipList from './components/ClipList';
@ -14,7 +15,7 @@ import { useAppDispatch, useAppSelector } from './hooks';
import { store } from '../redux/main';
import { useNavigate } from 'react-router-dom';
import SettingsPage from './Settings';
import apiFetch from './api';
import { apiFetch, getBaseUrl } from './api';
function MainPage() {
const dispatch = useAppDispatch();
@ -28,19 +29,40 @@ function MainPage() {
const [newCollectionName, setNewCollectionName] = useState<string>('');
const navigate = useNavigate();
useEffect(() => {}, []);
useEffect(() => {
const fetchMetadata = async () => {
try {
const response = await apiFetch('meta');
const data = await response.json();
dispatch({ type: 'metadata/setAllData', payload: data });
} catch (error) {
console.error('Error fetching metadata:', error);
let newSocket: any = null;
const initializeSocket = async () => {
const baseUrl = await getBaseUrl();
newSocket = io(baseUrl);
newSocket.on('connect', () => {
console.log('Connected to WebSocket server');
});
newSocket.on('full_data', (data: any) => {
console.log('Received full_data from server:', data);
dispatch({
type: 'metadata/setAllData',
payload: { collections: data },
});
});
newSocket.on('new_clip', (data: any) => {
console.log('Received new_clips from server:', data);
dispatch({
type: 'metadata/addNewClip',
payload: { clip: data },
});
});
};
initializeSocket();
return () => {
if (newSocket) {
newSocket.off('connect');
newSocket.off('full_data');
newSocket.off('new_clip');
newSocket.disconnect();
}
};
fetchMetadata();
const intervalId = setInterval(fetchMetadata, 5000);
return () => clearInterval(intervalId);
}, [dispatch]);
useEffect(() => {

View File

@ -1,11 +1,14 @@
import React, { useEffect, useState } from 'react';
// import { ipcRenderer } from 'electron';
import { useNavigate } from 'react-router-dom';
import './App.css';
import TextField from '@mui/material/TextField';
import Select from '@mui/material/Select';
import MenuItem from '@mui/material/MenuItem';
import apiFetch from './api';
import { IconButton } from '@mui/material';
import MoreHorizIcon from '@mui/icons-material/MoreHoriz';
import { apiFetch } from './api';
type AudioDevice = {
index: number;
@ -123,18 +126,22 @@ export default function SettingsPage() {
};
const handleFolderChange = async () => {
// Replace with actual folder picker
// Example: const folder = await window.api.selectFolder();
// const folder = window.prompt(
// 'Enter output folder path:',
// settings.outputFolder,
// );
// if (folder !== null) {
// setSettings((prev) => ({
// ...prev,
// outputFolder: folder,
// }));
// }
await window.electron.ipcRenderer
.invoke('select-directory')
.then((result) => {
if (result) {
setSettings((prev) => ({
...prev,
save_path: result,
}));
sendSettingsToBackend({
...settings,
save_path: result,
});
}
return null;
});
return null;
};
return (
@ -259,13 +266,22 @@ export default function SettingsPage() {
value={settings.save_path}
className="ml-2 w-[300px]"
/>
<button
<IconButton
component="label"
size="small"
tabIndex={-1}
onClick={handleFolderChange}
>
<MoreHorizIcon />
</IconButton>
{/* <button
type="button"
onClick={handleFolderChange}
className="ml-2 px-3 py-1 rounded bg-plumDark text-offwhite hover:bg-plum"
>
<VisuallyHiddenInput type="file" />
...
</button>
</button> */}
</div>
</div>
</div>

View File

@ -1,4 +1,4 @@
const getBaseUrl = async () => {
export const getBaseUrl = async () => {
const port = await window.audio.getPort();
if (port.error || !port.port) {
return `http://localhost:5010`;
@ -7,7 +7,7 @@ const getBaseUrl = async () => {
return `http://localhost:${port.port}`;
};
export default async function apiFetch(endpoint: string, options = {}) {
export async function apiFetch(endpoint: string, options = {}) {
const url = `${await getBaseUrl()}/${endpoint}`;
return fetch(url, options);
}

View File

@ -12,10 +12,10 @@ import {
verticalListSortingStrategy,
} from '@dnd-kit/sortable';
import { restrictToVerticalAxis } from '@dnd-kit/modifiers';
import AudioTrimmer from './AudioTrimer';
import AudioTrimmer from './Trimmer/AudioTrimer';
import { ClipMetadata } from '../../redux/types';
import { useAppDispatch, useAppSelector } from '../hooks';
import apiFetch from '../api';
import { apiFetch } from '../api';
export interface ClipListProps {
collection: string;

View File

@ -5,27 +5,22 @@ import React, {
useCallback,
useRef,
} from 'react';
import Dialog from '@mui/material/Dialog';
import DialogTitle from '@mui/material/DialogTitle';
import DialogContent from '@mui/material/DialogContent';
import DialogActions from '@mui/material/DialogActions';
import Slider from '@mui/material/Slider';
import ToggleButton from '@mui/material/ToggleButton';
import ToggleButtonGroup from '@mui/material/ToggleButtonGroup';
import { useWavesurfer } from '@wavesurfer/react';
import RegionsPlugin from 'wavesurfer.js/dist/plugins/regions.esm.js';
import ZoomPlugin from 'wavesurfer.js/dist/plugins/zoom.esm.js';
import PlayArrowIcon from '@mui/icons-material/PlayArrow';
import PauseIcon from '@mui/icons-material/Pause';
import ArrowForwardIcon from '@mui/icons-material/ArrowForward';
import ArrowDownwardIcon from '@mui/icons-material/ArrowDownward';
import DeleteIcon from '@mui/icons-material/Delete';
import { useSortable } from '@dnd-kit/sortable';
import { CSS } from '@dnd-kit/utilities';
import { ClipMetadata, PlaybackType } from '../../redux/types';
import { useAppSelector } from '../hooks';
import PlayStopIcon from './playStopIcon';
import PlayOverlapIcon from './playOverlapIcon';
import { ClipMetadata, PlaybackType } from '../../../redux/types';
import { useAppSelector } from '../../hooks';
import PlayStopIcon from '../icons/playStopIcon';
import PlayOverlapIcon from '../icons/playOverlapIcon';
import NameEditDialog from './dialogs/NameEditDialog';
import DeleteClipDialog from './dialogs/DeleteClipDialog';
import TitleBlock from './TitleBlock';
import ClipButtonRow from './ClipButtonRow';
export interface AudioTrimmerProps {
metadata: ClipMetadata;
@ -42,33 +37,23 @@ export default function AudioTrimmer({
}: AudioTrimmerProps) {
const { attributes, listeners, setNodeRef, transform, transition } =
useSortable({ id: metadata.filename });
// Dialog state for editing name
const rootRef = useRef<HTMLDivElement | null>(null);
const [isVisible, setIsVisible] = useState(false);
const [editDialogOpen, setEditDialogOpen] = useState(false);
const [deleteDialogOpen, setDeleteDialogOpen] = useState(false);
const [dropdownOpen, setDropdownOpen] = useState(false);
const [nameInput, setNameInput] = useState<string>(metadata.name);
const [volumeInput, setVolumeInput] = useState<number>(metadata.volume ?? 1);
const collectionNames = useAppSelector((state) =>
state.collections.map((col) => col.name),
);
useEffect(() => {
setNameInput(metadata.name);
}, [metadata.name]);
const openEditDialog = () => setEditDialogOpen(true);
const closeEditDialog = () => setEditDialogOpen(false);
const handleDialogSave = () => {
if (nameInput.trim() && nameInput !== metadata.name) {
const updated = { ...metadata, name: nameInput.trim() };
const handleDialogSave = (newName: string) => {
if (newName.trim() && newName !== metadata.name) {
const updated = { ...metadata, name: newName.trim() };
if (onSave) onSave(updated);
}
closeEditDialog();
setEditDialogOpen(false);
};
const [blobUrl, setBlobUrl] = useState<string | undefined>(undefined);
const containerRef = useRef(null);
// const [clipStart, setClipStart] = useState<number | undefined>(undefined);
// const [clipEnd, setClipEnd] = useState<number | undefined>(undefined);
@ -83,16 +68,12 @@ export default function AudioTrimmer({
[],
);
const fileBaseName =
metadata.filename.split('\\').pop()?.split('/').pop() || 'Unknown';
const { wavesurfer, isReady, isPlaying } = useWavesurfer({
container: containerRef,
height: 100,
waveColor: '#ccb1ff',
progressColor: '#6e44ba',
hideScrollbar: true,
url: blobUrl,
plugins,
});
@ -202,25 +183,42 @@ export default function AudioTrimmer({
}, [onRegionCreated, onRegionUpdated, plugins]);
useEffect(() => {
let url: string | null = null;
const node = rootRef.current;
if (!node) return;
const observer = new window.IntersectionObserver(
([entry]) => {
if (entry.isIntersecting) {
setIsVisible(true);
}
},
{ threshold: 0.1 },
);
observer.observe(node);
// eslint-disable-next-line consistent-return
return () => {
observer.disconnect();
};
}, []);
useEffect(() => {
if (!isVisible) return;
let cancelled = false;
async function fetchAudio() {
// console.log('Loading audio buffer for file:', filename);
const buffer = await window.audio.loadAudioBuffer(metadata.filename);
// console.log('Received buffer:', buffer.buffer);
if (cancelled) return;
if (buffer.buffer && !buffer.error) {
const audioData = buffer.buffer
? new Uint8Array(buffer.buffer)
: buffer;
url = URL.createObjectURL(new Blob([audioData]));
// console.log('Created blob URL:', url);
setBlobUrl(url);
wavesurfer?.loadBlob(new Blob([audioData]));
}
}
fetchAudio();
// eslint-disable-next-line consistent-return
return () => {
if (url) URL.revokeObjectURL(url);
cancelled = true;
};
}, [metadata.filename]);
}, [isVisible, metadata.filename, wavesurfer]);
const onPlayPause = () => {
if (wavesurfer === null) return;
@ -245,7 +243,10 @@ export default function AudioTrimmer({
return (
<div
ref={setNodeRef}
ref={(el) => {
setNodeRef(el);
rootRef.current = el;
}}
style={{
transform: CSS.Transform.toString(transform),
transition,
@ -254,6 +255,21 @@ export default function AudioTrimmer({
}}
className="shadow-[0_2px_8px_rgba(0,0,0,0.5)] m-2 rounded-lg bg-darkDrop"
>
<NameEditDialog
open={editDialogOpen}
onCancel={() => setEditDialogOpen(false)}
startValue={metadata.name}
onSave={handleDialogSave}
/>
<DeleteClipDialog
open={deleteDialogOpen}
onCancel={() => setDeleteDialogOpen(false)}
onDelete={() => {
setDeleteDialogOpen(false);
if (onDelete) onDelete(metadata);
}}
/>
<div
// eslint-disable-next-line react/jsx-props-no-spreading
{...attributes}
@ -273,137 +289,22 @@ export default function AudioTrimmer({
{/* <div className="flex flex-col"> */}
<div className="ml-4 mr-2 p-2">
<div className="grid justify-items-stretch grid-cols-2">
<div className="mb-5px flex flex-col">
<span
className="font-bold text-lg text-white mb-1 cursor-pointer"
onClick={openEditDialog}
onKeyDown={(e) => {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault();
openEditDialog();
<TitleBlock
name={metadata.name}
filename={metadata.filename}
onNameClick={() => setEditDialogOpen(true)}
/>
<ClipButtonRow
isPlaying={isPlaying}
collectionNames={collectionNames}
onPlayPause={onPlayPause}
onMove={(collectionName) => {
if (onMove !== undefined) {
onMove(collectionName, metadata);
}
}}
title="Click to edit name"
tabIndex={0}
role="button"
style={{ outline: 'none' }}
>
{metadata.name}
</span>
<span className="text-sm text-neutral-500">{fileBaseName}</span>
</div>
<Dialog
open={editDialogOpen}
onClose={closeEditDialog}
slotProps={{
paper: { sx: { backgroundColor: '#1a1a1a', color: 'white' } },
}}
>
<DialogTitle>Edit Clip Name</DialogTitle>
<DialogContent>
<textarea
autoFocus
className="font-bold text-lg bg-transparent outline-none border-b border-plum focus:border-plumDark text-white mb-1 w-full text-center resize-y"
value={nameInput}
onChange={(e) => setNameInput(e.target.value)}
rows={3}
onFocus={(event) => event.target.select()}
aria-label="Edit clip name"
style={{ minHeight: '3em' }}
onDelete={() => setDeleteDialogOpen(true)}
/>
</DialogContent>
<DialogActions>
<button
type="button"
onClick={closeEditDialog}
className="bg-plum hover:bg-plumDark text-white font-bold h-10 px-4 rounded-md"
>
Cancel
</button>
<button
type="button"
onClick={handleDialogSave}
className="bg-plum hover:bg-plumDark text-white font-bold h-10 px-4 rounded-md"
>
Save
</button>
</DialogActions>
</Dialog>
<Dialog
open={deleteDialogOpen}
onClose={() => setDeleteDialogOpen(false)}
slotProps={{
paper: { sx: { backgroundColor: '#1a1a1a', color: 'white' } },
}}
>
<DialogTitle>Confirm Delete</DialogTitle>
<DialogContent>
Are you sure you want to delete this clip?
</DialogContent>
<DialogActions>
<button
type="button"
onClick={() => setDeleteDialogOpen(false)}
className="bg-plum hover:bg-plumDark text-white font-bold h-10 px-4 rounded-md"
>
Cancel
</button>
<button
type="button"
onClick={() => {
setDeleteDialogOpen(false);
if (onDelete) onDelete(metadataRef.current);
}}
className="bg-plum hover:bg-plumDark text-white font-bold h-10 px-4 rounded-md"
>
Delete
</button>
</DialogActions>
</Dialog>
<div className="flex justify-end">
<button
type="button"
className="bg-plum hover:bg-plumDark text-white font-bold h-11 w-11 rounded-md ml-1"
onClick={onPlayPause}
>
{isPlaying ? <PauseIcon /> : <PlayArrowIcon />}
</button>
<div className="relative inline-block">
<button
type="button"
className="bg-plum hover:bg-plumDark text-white font-bold h-11 w-11 rounded-md ml-1"
onClick={() => setDropdownOpen((prev) => !prev)}
>
{dropdownOpen ? <ArrowDownwardIcon /> : <ArrowForwardIcon />}
</button>
{dropdownOpen && (
<div className="absolute z-10 mt-2 w-40 bg-midnight rounded-md shadow-lg">
{collectionNames.map((name) => (
<button
key={name}
type="button"
className="block w-full text-left px-4 py-2 text-white hover:bg-plumDark"
onClick={() => {
setDropdownOpen(false);
if (onMove) onMove(name, metadata);
}}
>
{name}
</button>
))}
</div>
)}
</div>
<button
type="button"
className="bg-plum hover:bg-plumDark text-white font-bold h-11 w-11 rounded-md ml-1"
onClick={() => setDeleteDialogOpen(true)}
>
<DeleteIcon />
</button>
</div>
</div>
<div className="m-1 wavesurfer-scroll-container">
<div ref={containerRef} className="wavesurfer-inner" />
@ -428,24 +329,6 @@ export default function AudioTrimmer({
color="secondary"
className="p-0 m-0"
/>
{/* <input
type="range"
min={0}
max={1}
step={0.01}
value={volumeInput}
onChange={(e) => {
const newVolume = parseFloat(e.target.value);
setVolumeInput(newVolume);
}}
onDragEnd={(e) => {
console.log('Volume change:');
// const newVolume = parseFloat(e.target.value);
// if (onSave) onSave({ ...metadata, volume: newVolume });
}}
className="mx-2 w-full accent-plum"
aria-label="Volume slider"
/> */}
</div>
<div className="w-1/5 flex justify-end text-sm text-neutral-500">
<ToggleButtonGroup value={metadata.playbackType}>

View File

@ -0,0 +1,67 @@
import PlayArrowIcon from '@mui/icons-material/PlayArrow';
import PauseIcon from '@mui/icons-material/Pause';
import ArrowForwardIcon from '@mui/icons-material/ArrowForward';
import ArrowDownwardIcon from '@mui/icons-material/ArrowDownward';
import DeleteIcon from '@mui/icons-material/Delete';
import { useState } from 'react';
export default function ClipButtonRow({
isPlaying,
collectionNames,
onPlayPause,
onMove,
onDelete,
}: {
isPlaying: boolean;
collectionNames: string[];
onPlayPause: () => void;
onMove?: (collectionName: string) => void;
onDelete?: () => void;
}) {
const [dropdownOpen, setDropdownOpen] = useState(false);
return (
<div className="flex justify-end">
<button
type="button"
className="bg-plum hover:bg-plumDark text-white font-bold h-11 w-11 rounded-md ml-1"
onClick={onPlayPause}
>
{isPlaying ? <PauseIcon /> : <PlayArrowIcon />}
</button>
<div className="relative inline-block">
<button
type="button"
className="bg-plum hover:bg-plumDark text-white font-bold h-11 w-11 rounded-md ml-1"
onClick={() => setDropdownOpen((prev) => !prev)}
>
{dropdownOpen ? <ArrowDownwardIcon /> : <ArrowForwardIcon />}
</button>
{dropdownOpen && (
<div className="absolute z-10 mt-2 w-40 bg-midnight rounded-md shadow-lg">
{collectionNames.map((name) => (
<button
key={name}
type="button"
className="block w-full text-left px-4 py-2 text-white hover:bg-plumDark"
onClick={() => {
setDropdownOpen(false);
if (onMove) onMove(name);
}}
>
{name}
</button>
))}
</div>
)}
</div>
<button
type="button"
className="bg-plum hover:bg-plumDark text-white font-bold h-11 w-11 rounded-md ml-1"
onClick={() => onDelete && onDelete()}
>
<DeleteIcon />
</button>
</div>
);
}

View File

@ -0,0 +1,27 @@
export default function TitleBlock({
name,
filename,
onNameClick,
}: {
name: string;
filename: string;
onNameClick: () => void;
}) {
const basename = filename.split('\\').pop()?.split('/').pop() || 'Unknown';
return (
<div className="mb-5px flex flex-col">
<span
className="font-bold text-lg text-white mb-1 cursor-pointer"
onClick={onNameClick}
onKeyDown={(e) => {}}
title="Click to edit name"
tabIndex={0}
role="button"
style={{ outline: 'none' }}
>
{name}
</span>
<span className="text-sm text-neutral-500">{basename}</span>
</div>
);
}

View File

@ -0,0 +1,46 @@
import {
Dialog,
DialogTitle,
DialogContent,
DialogActions,
} from '@mui/material';
export default function DeleteClipDialog({
open,
onCancel,
onDelete,
}: {
open: boolean;
onCancel: () => void;
onDelete: () => void;
}) {
return (
<Dialog
open={open}
onClose={onCancel}
slotProps={{
paper: { sx: { backgroundColor: '#1a1a1a', color: 'white' } },
}}
>
<DialogTitle>Confirm Delete</DialogTitle>
<DialogContent>Are you sure you want to delete this clip?</DialogContent>
<DialogActions>
<button
type="button"
onClick={onCancel}
className="bg-plum hover:bg-plumDark text-white font-bold h-10 px-4 rounded-md"
>
Cancel
</button>
<button
type="button"
onClick={onDelete}
autoFocus
className="bg-plum hover:bg-plumDark text-white font-bold h-10 px-4 rounded-md"
>
Delete
</button>
</DialogActions>
</Dialog>
);
}

View File

@ -0,0 +1,70 @@
import { useEffect, useState } from 'react';
import {
Dialog,
DialogTitle,
DialogContent,
DialogActions,
TextField,
} from '@mui/material';
export default function NameEditDialog({
open,
startValue,
onCancel,
onSave,
}: {
open: boolean;
startValue: string;
onCancel: () => void;
onSave: (newName: string) => void;
}) {
const [input, setInput] = useState(startValue);
useEffect(() => {
if (open) {
setInput(startValue);
}
}, [open, startValue]);
return (
<Dialog
open={open}
onClose={onCancel}
slotProps={{
paper: { sx: { backgroundColor: '#1a1a1a', color: 'white' } },
}}
>
<DialogTitle>Edit Clip Name</DialogTitle>
<DialogContent>
<TextField
autoFocus
multiline
variant="standard"
className="font-bold text-lg bg-transparent outline-none border-b border-plum focus:border-plumDark text-white mb-1 w-full text-center resize-y"
value={input}
onChange={(e) => {
setInput(e.target.value);
}}
onFocus={(event) => event.target.select()}
aria-label="Edit clip name"
/>
</DialogContent>
<DialogActions>
<button
type="button"
onClick={onCancel}
className="bg-plum hover:bg-plumDark text-white font-bold h-10 px-4 rounded-md"
>
Cancel
</button>
<button
type="button"
onClick={() => onSave(input)}
className="bg-plum hover:bg-plumDark text-white font-bold h-10 px-4 rounded-md"
>
Save
</button>
</DialogActions>
</Dialog>
);
}

View File

@ -6,7 +6,7 @@
http-equiv="Content-Security-Policy"
content="script-src 'self' 'unsafe-inline'"
/>
<title>Hello Electron React!</title>
<title>ClipTrim</title>
</head>
<body>
<div id="root"></div>

421
electron-ui/test_meta.json Normal file
View File

@ -0,0 +1,421 @@
[
{
"name": "Uncategorized",
"id": 0,
"clips": []
},
{
"name": "mason",
"id": 1,
"clips": [
{
"filename": "C:\\Users\\mickl\\Music\\clips\\original\\audio_capture_20250105_131700.wav",
"name": "lich",
"playbackType": "playOverlap",
"volume": 1,
"startTime": 27.371372936207585,
"endTime": 30
},
{
"filename": "C:\\Users\\mickl\\Music\\clips\\original\\audio_capture_20250119_173448.wav",
"name": "nic",
"playbackType": "playOverlap",
"volume": 1,
"startTime": 9.897134459955918,
"endTime": 10.62821454812639
},
{
"filename": "C:\\Users\\mickl\\Music\\clips\\original\\audio_capture_20250119_173654.wav",
"name": "racist",
"playbackType": "playOverlap",
"volume": 1,
"startTime": 7.92372881355932,
"endTime": 9.682203389830498
},
{
"filename": "C:\\Users\\mickl\\Music\\clips\\original\\audio_capture_20250120_210843.wav",
"name": "dildo",
"playbackType": "playOverlap",
"volume": 1,
"startTime": 11.227565151875025,
"endTime": 13.20035827476919
},
{
"filename": "C:\\Users\\mickl\\Music\\clips\\original\\audio_capture_20250121_223502.wav",
"name": "latter",
"playbackType": "playOverlap",
"volume": 1,
"startTime": 11.440677966101688,
"endTime": 12.499999999999996
},
{
"filename": "C:\\Users\\mickl\\Music\\clips\\original\\audio_capture_20250124_214433.wav",
"name": "ahh",
"playbackType": "playOverlap",
"volume": 1,
"startTime": 10,
"endTime": 10.656779661016953
},
{
"filename": "C:\\Users\\mickl\\Music\\clips\\original\\audio_capture_20250131_204903.wav",
"name": "tight",
"playbackType": "playOverlap",
"volume": 1,
"startTime": 9.7457627118644,
"endTime": 11.52542372881357
},
{
"filename": "C:\\Users\\mickl\\Music\\clips\\original\\audio_capture_20250308_104030.wav",
"name": "rape",
"playbackType": "playOverlap",
"volume": 1,
"startTime": 3.7923728813559365,
"endTime": 5.677966101694913
},
{
"filename": "C:\\Users\\mickl\\Music\\clips\\original\\audio_capture_20250328_212948.wav",
"name": "wig",
"playbackType": "playOverlap",
"volume": 1,
"startTime": 10.31779661016946,
"endTime": 11.038135593220328
},
{
"filename": "C:\\Users\\mickl\\Music\\clips\\original\\audio_capture_20250419_140818.wav",
"name": "queef",
"playbackType": "playOverlap",
"volume": 1,
"startTime": 12.47881355932203,
"endTime": 13.347457627118642
},
{
"filename": "C:\\Users\\mickl\\Music\\clips\\original\\audio_capture_20250503_183629.wav",
"name": "wood",
"playbackType": "playOverlap",
"volume": 1,
"startTime": 10.82627118644066,
"endTime": 11.546610169491522
},
{
"filename": "C:\\Users\\mickl\\Music\\clips\\original\\audio_capture_20250707_213558.wav",
"name": "bam",
"playbackType": "playOverlap",
"volume": 1,
"startTime": 13.728813559321997,
"endTime": 14.300847457627134
},
{
"filename": "C:\\Users\\mickl\\Music\\clips\\original\\audio_capture_20250707_222904.wav",
"name": "uhh",
"playbackType": "playOverlap",
"volume": 1,
"startTime": 13.199152542372879,
"endTime": 14.830508474576275
},
{
"filename": "C:\\Users\\mickl\\Music\\clips\\original\\audio_capture_20250808_194926.wav",
"name": "rights",
"playbackType": "playOverlap",
"volume": 1,
"startTime": 9.131355932203387,
"endTime": 10.69915254237289
},
{
"filename": "C:\\Users\\mickl\\Music\\clips\\original\\audio_capture_20250809_193435.wav",
"name": "u r wet",
"playbackType": "playOverlap",
"volume": 1,
"startTime": 8.983050847457612,
"endTime": 10.14830508474577
},
{
"filename": "C:\\Users\\mickl\\Music\\clips\\original\\audio_capture_20250809_222039.wav",
"name": "run",
"playbackType": "playOverlap",
"volume": 1,
"startTime": 4.216101694915256,
"endTime": 11.038135593220332
},
{
"filename": "C:\\Users\\mickl\\Music\\clips\\original\\audio_capture_20250814_215842.wav",
"name": "suprise",
"playbackType": "playOverlap",
"volume": 1,
"startTime": 11.927966101694913,
"endTime": 14.300847457627116
},
{
"filename": "C:\\Users\\mickl\\Music\\clips\\original\\audio_capture_20250920_174822.wav",
"name": "my",
"playbackType": "playOverlap",
"volume": 1,
"startTime": 5.736975857687425,
"endTime": 6.202880135535784
},
{
"filename": "C:\\Users\\mickl\\Music\\clips\\original\\audio_capture_20250920_174950.wav",
"name": "whatsup",
"playbackType": "playOverlap",
"volume": 1,
"startTime": 2.870606674248936,
"endTime": 3.3193015062831197
},
{
"filename": "C:\\Users\\mickl\\Music\\clips\\original\\audio_capture_20251018_211620.wav",
"name": "cheeks",
"playbackType": "playOverlap",
"volume": 1,
"startTime": 10.338983050847464,
"endTime": 12.394067796610184
},
{
"filename": "C:\\Users\\mickl\\Music\\clips\\original\\audio_capture_20251031_211310.wav",
"name": "michal",
"playbackType": "playOverlap",
"volume": 1,
"startTime": 8.516949152542374,
"endTime": 12.415254237288133
},
{
"filename": "C:\\Users\\mickl\\Music\\clips\\original\\audio_capture_20251107_222607.wav",
"name": "blegh",
"playbackType": "playOverlap",
"volume": 1,
"startTime": 9.216101694915253,
"endTime": 9.957627118644073
},
{
"filename": "C:\\Users\\mickl\\Music\\clips\\original\\audio_capture_20251115_201357.wav",
"name": "bohemian",
"playbackType": "playOverlap",
"volume": 1,
"startTime": 9.618644067796604,
"endTime": 11.274508356463695
},
{
"filename": "C:\\Users\\mickl\\Music\\clips\\original\\audio_capture_20251213_114932.wav",
"name": "electro",
"playbackType": "playOverlap",
"volume": 1,
"startTime": 9.915254237288137,
"endTime": 13.771186440677946
},
{
"filename": "C:\\Users\\mickl\\Music\\clips\\original\\audio_capture_20260201_111049.wav",
"name": "nword",
"playbackType": "playOverlap",
"volume": 1,
"startTime": 8.834745762711867,
"endTime": 10.911016949152565
},
{
"filename": "C:\\Users\\mickl\\Music\\clips\\original\\audio_capture_20260206_230124.wav",
"name": "fist",
"playbackType": "playOverlap",
"volume": 1,
"startTime": 12.458333333333336,
"endTime": 13.708333333333327
}
]
},
{
"name": "jake",
"id": 2,
"clips": [
{
"filename": "C:\\Users\\mickl\\Music\\clips\\original\\audio_capture_20250117_194006.wav",
"name": "do it",
"playbackType": "playOverlap",
"volume": 1,
"startTime": 14.152542372881365,
"endTime": 14.936440677966102
},
{
"filename": "C:\\Users\\mickl\\Music\\clips\\original\\audio_capture_20250121_223258.wav",
"name": "cooch",
"playbackType": "playOverlap",
"volume": 1,
"startTime": 8.538135593220337,
"endTime": 10.656779661016952
},
{
"filename": "C:\\Users\\mickl\\Music\\clips\\original\\audio_capture_20250215_214039.wav",
"name": "domestic",
"playbackType": "playOverlap",
"volume": 1,
"startTime": 10.40254237288135,
"endTime": 13.05084745762703
},
{
"filename": "C:\\Users\\mickl\\Music\\clips\\original\\audio_capture_20250412_134821.wav",
"name": "god",
"playbackType": "playOverlap",
"volume": 1,
"startTime": 11.927966101694915,
"endTime": 13.834745762711863
},
{
"filename": "C:\\Users\\mickl\\Music\\clips\\original\\audio_capture_20250606_212121.wav",
"name": "poop\nmyself",
"playbackType": "playOverlap",
"volume": 1,
"startTime": 7.881355932203395,
"endTime": 12.055084745762716
},
{
"filename": "C:\\Users\\mickl\\Music\\clips\\original\\audio_capture_20250719_120451.wav",
"name": "tasmania",
"playbackType": "playOverlap",
"volume": 1,
"startTime": 11.038135593220334,
"endTime": 13.686440677966088
},
{
"filename": "C:\\Users\\mickl\\Music\\clips\\original\\audio_capture_20250822_205916.wav",
"name": "jews",
"playbackType": "playOverlap",
"volume": 1,
"startTime": 11.122881355932197,
"endTime": 12.097457627118638
},
{
"filename": "C:\\Users\\mickl\\Music\\clips\\original\\audio_capture_20251026_211500.wav",
"name": "terror",
"playbackType": "playOverlap",
"volume": 1,
"startTime": 10.572033898305074,
"endTime": 11.588983050847439
},
{
"filename": "C:\\Users\\mickl\\Music\\clips\\original\\audio_capture_20251108_170721.wav",
"name": "toon\ntown",
"playbackType": "playOverlap",
"volume": 1,
"startTime": 5.148305084745765,
"endTime": 8.411016949152545
},
{
"filename": "C:\\Users\\mickl\\Music\\clips\\original\\audio_capture_20260103_222442.wav",
"name": "whooping",
"playbackType": "playOverlap",
"volume": 1,
"startTime": 7.309322033898307,
"endTime": 9.046610169491542
},
{
"filename": "C:\\Users\\mickl\\Music\\clips\\original\\audio_capture_20260107_210712.wav",
"name": "no head",
"playbackType": "playOverlap",
"volume": 1,
"startTime": 8.050847457627118,
"endTime": 9.279661016949134
}
]
},
{
"name": "isaac",
"id": 3,
"clips": [
{
"filename": "C:\\Users\\mickl\\Music\\clips\\original\\audio_capture_20250121_203752.wav",
"name": "blow",
"playbackType": "playOverlap",
"volume": 1,
"startTime": 10.800018422991895,
"endTime": 11.453804347826084
},
{
"filename": "C:\\Users\\mickl\\Music\\clips\\original\\audio_capture_20250125_002323.wav",
"name": "frying",
"playbackType": "playOverlap",
"volume": 1,
"startTime": 9.337093249867106,
"endTime": 11.49862694147519
},
{
"filename": "C:\\Users\\mickl\\Music\\clips\\original\\audio_capture_20250125_230923.wav",
"name": "cum",
"playbackType": "playOverlap",
"volume": 1,
"startTime": 8.728813559322031,
"endTime": 9.894067796610173
},
{
"filename": "C:\\Users\\mickl\\Music\\clips\\original\\audio_capture_20250126_131833.wav",
"name": "liquid",
"playbackType": "playOverlap",
"volume": 1,
"startTime": 10.487288135593221,
"endTime": 11.86440677966102
},
{
"filename": "C:\\Users\\mickl\\Music\\clips\\original\\audio_capture_20250131_220452.wav",
"name": "nuts",
"playbackType": "playOverlap",
"volume": 1,
"startTime": 8.135593220338984,
"endTime": 8.983050847457633
},
{
"filename": "C:\\Users\\mickl\\Music\\clips\\original\\audio_capture_20251101_205146.wav",
"name": "hard",
"playbackType": "playOverlap",
"volume": 1,
"startTime": 8.283898305084744,
"endTime": 10.720338983050835
}
]
},
{
"name": "nat",
"id": 4,
"clips": [
{
"filename": "C:\\Users\\mickl\\Music\\clips\\original\\audio_capture_20250125_171754.wav",
"name": "hot dog",
"playbackType": "playOverlap",
"volume": 1,
"startTime": 8.644067796610168,
"endTime": 11.05932203389828
},
{
"filename": "C:\\Users\\mickl\\Music\\clips\\original\\audio_capture_20250131_212540.wav",
"name": "plink",
"playbackType": "playOverlap",
"volume": 1,
"startTime": 10.40254237288135,
"endTime": 12.012711864406779
}
]
},
{
"name": "misc",
"id": 5,
"clips": [
{
"filename": "C:\\Users\\mickl\\Music\\clips\\original\\audio_capture_20250223_110900.wav",
"name": "bounce",
"playbackType": "playOverlap",
"volume": 1,
"startTime": 2.521186440677966,
"endTime": 7.4152542372881225
},
{
"filename": "C:\\Users\\mickl\\Music\\clips\\original\\audio_capture_20250228_221700.wav",
"name": "avada",
"playbackType": "playOverlap",
"volume": 1,
"startTime": 1.8220338983050826,
"endTime": 5.338983050847453
},
{
"filename": "C:\\Users\\mickl\\Music\\clips\\original\\audio_capture_20251212_192830.wav",
"name": "sandler",
"playbackType": "playOverlap",
"volume": 1,
"startTime": 9.576271186440678,
"endTime": 12.394067796610187
}
]
}
]

View File

@ -1,44 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
using SocketIOClient;
namespace ClientTest
{
public class Client
{
private SocketIO client;
public Client()
{
client = new SocketIO(new Uri("http://localhost:5010/"));
client.Options.AutoUpgrade = false;
client.Options.ConnectionTimeout = TimeSpan.FromSeconds(10);
client.Options.Reconnection = false;
client.On("test_event", ctx =>
{
Console.WriteLine($"Received test event: {ctx.RawText}");
return Task.CompletedTask;
});
client.On("collection_updated", ctx =>
{
Console.WriteLine($"Received test event: {ctx.RawText}");
return Task.CompletedTask;
});
client.OnAny((string eventName, IEventContext ctx) =>
{
Console.WriteLine($"got event: {eventName} \n {ctx.RawText}");
return Task.CompletedTask;
});
client.ConnectAsync().Wait();
client.EmitAsync("test_event", [""]);
}
}
}

View File

@ -1,14 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="SocketIOClient" Version="4.0.0.2" />
</ItemGroup>
</Project>

View File

@ -1,10 +0,0 @@
// See https://aka.ms/new-console-template for more information
using ClientTest;
Console.WriteLine("Hello, World!");
Client client = new Client();
while (true)
{
await Task.Delay(1000);
}

View File

@ -1,296 +0,0 @@
{
"runtimeTarget": {
"name": ".NETCoreApp,Version=v8.0",
"signature": ""
},
"compilationOptions": {},
"targets": {
".NETCoreApp,Version=v8.0": {
"ClientTest/1.0.0": {
"dependencies": {
"SocketIOClient": "4.0.0.2"
},
"runtime": {
"ClientTest.dll": {}
}
},
"Microsoft.Extensions.DependencyInjection/10.0.2": {
"dependencies": {
"Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.2"
},
"runtime": {
"lib/net8.0/Microsoft.Extensions.DependencyInjection.dll": {
"assemblyVersion": "10.0.0.0",
"fileVersion": "10.0.225.61305"
}
}
},
"Microsoft.Extensions.DependencyInjection.Abstractions/10.0.2": {
"runtime": {
"lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll": {
"assemblyVersion": "10.0.0.0",
"fileVersion": "10.0.225.61305"
}
}
},
"Microsoft.Extensions.Logging/10.0.2": {
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "10.0.2",
"Microsoft.Extensions.Logging.Abstractions": "10.0.2",
"Microsoft.Extensions.Options": "10.0.2"
},
"runtime": {
"lib/net8.0/Microsoft.Extensions.Logging.dll": {
"assemblyVersion": "10.0.0.0",
"fileVersion": "10.0.225.61305"
}
}
},
"Microsoft.Extensions.Logging.Abstractions/10.0.2": {
"dependencies": {
"Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.2",
"System.Diagnostics.DiagnosticSource": "10.0.2"
},
"runtime": {
"lib/net8.0/Microsoft.Extensions.Logging.Abstractions.dll": {
"assemblyVersion": "10.0.0.0",
"fileVersion": "10.0.225.61305"
}
}
},
"Microsoft.Extensions.Options/10.0.2": {
"dependencies": {
"Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.2",
"Microsoft.Extensions.Primitives": "10.0.2"
},
"runtime": {
"lib/net8.0/Microsoft.Extensions.Options.dll": {
"assemblyVersion": "10.0.0.0",
"fileVersion": "10.0.225.61305"
}
}
},
"Microsoft.Extensions.Primitives/10.0.2": {
"runtime": {
"lib/net8.0/Microsoft.Extensions.Primitives.dll": {
"assemblyVersion": "10.0.0.0",
"fileVersion": "10.0.225.61305"
}
}
},
"Newtonsoft.Json/13.0.4": {
"runtime": {
"lib/net6.0/Newtonsoft.Json.dll": {
"assemblyVersion": "13.0.0.0",
"fileVersion": "13.0.4.30916"
}
}
},
"SocketIOClient/4.0.0.2": {
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "10.0.2",
"Microsoft.Extensions.Logging": "10.0.2",
"SocketIOClient.Common": "4.0.0",
"SocketIOClient.Serializer": "4.0.0.1",
"SocketIOClient.Serializer.NewtonsoftJson": "4.0.0.1",
"System.Text.Json": "10.0.2"
},
"runtime": {
"lib/net8.0/SocketIOClient.dll": {
"assemblyVersion": "4.0.0.2",
"fileVersion": "4.0.0.2"
}
}
},
"SocketIOClient.Common/4.0.0": {
"runtime": {
"lib/net8.0/SocketIOClient.Common.dll": {
"assemblyVersion": "4.0.0.0",
"fileVersion": "4.0.0.0"
}
}
},
"SocketIOClient.Serializer/4.0.0.1": {
"dependencies": {
"SocketIOClient.Common": "4.0.0"
},
"runtime": {
"lib/net8.0/SocketIOClient.Serializer.dll": {
"assemblyVersion": "4.0.0.1",
"fileVersion": "4.0.0.1"
}
}
},
"SocketIOClient.Serializer.NewtonsoftJson/4.0.0.1": {
"dependencies": {
"Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.2",
"Newtonsoft.Json": "13.0.4",
"SocketIOClient.Common": "4.0.0",
"SocketIOClient.Serializer": "4.0.0.1"
},
"runtime": {
"lib/net8.0/SocketIOClient.Serializer.NewtonsoftJson.dll": {
"assemblyVersion": "4.0.0.1",
"fileVersion": "4.0.0.1"
}
}
},
"System.Diagnostics.DiagnosticSource/10.0.2": {
"runtime": {
"lib/net8.0/System.Diagnostics.DiagnosticSource.dll": {
"assemblyVersion": "10.0.0.0",
"fileVersion": "10.0.225.61305"
}
}
},
"System.IO.Pipelines/10.0.2": {
"runtime": {
"lib/net8.0/System.IO.Pipelines.dll": {
"assemblyVersion": "10.0.0.0",
"fileVersion": "10.0.225.61305"
}
}
},
"System.Text.Encodings.Web/10.0.2": {
"runtime": {
"lib/net8.0/System.Text.Encodings.Web.dll": {
"assemblyVersion": "10.0.0.0",
"fileVersion": "10.0.225.61305"
}
},
"runtimeTargets": {
"runtimes/browser/lib/net8.0/System.Text.Encodings.Web.dll": {
"rid": "browser",
"assetType": "runtime",
"assemblyVersion": "10.0.0.0",
"fileVersion": "10.0.225.61305"
}
}
},
"System.Text.Json/10.0.2": {
"dependencies": {
"System.IO.Pipelines": "10.0.2",
"System.Text.Encodings.Web": "10.0.2"
},
"runtime": {
"lib/net8.0/System.Text.Json.dll": {
"assemblyVersion": "10.0.0.0",
"fileVersion": "10.0.225.61305"
}
}
}
}
},
"libraries": {
"ClientTest/1.0.0": {
"type": "project",
"serviceable": false,
"sha512": ""
},
"Microsoft.Extensions.DependencyInjection/10.0.2": {
"type": "package",
"serviceable": true,
"sha512": "sha512-J/Zmp6fY93JbaiZ11ckWvcyxMPjD6XVwIHQXBjryTBgn7O6O20HYg9uVLFcZlNfgH78MnreE/7EH+hjfzn7VyA==",
"path": "microsoft.extensions.dependencyinjection/10.0.2",
"hashPath": "microsoft.extensions.dependencyinjection.10.0.2.nupkg.sha512"
},
"Microsoft.Extensions.DependencyInjection.Abstractions/10.0.2": {
"type": "package",
"serviceable": true,
"sha512": "sha512-zOIurr59+kUf9vNcsUkCvKWZv+fPosUZXURZesYkJCvl0EzTc9F7maAO4Cd2WEV7ZJJ0AZrFQvuH6Npph9wdBw==",
"path": "microsoft.extensions.dependencyinjection.abstractions/10.0.2",
"hashPath": "microsoft.extensions.dependencyinjection.abstractions.10.0.2.nupkg.sha512"
},
"Microsoft.Extensions.Logging/10.0.2": {
"type": "package",
"serviceable": true,
"sha512": "sha512-a0EWuBs6D3d7XMGroDXm+WsAi5CVVfjOJvyxurzWnuhBN9CO+1qHKcrKV1JK7H/T4ZtHIoVCOX/YyWM8K87qtw==",
"path": "microsoft.extensions.logging/10.0.2",
"hashPath": "microsoft.extensions.logging.10.0.2.nupkg.sha512"
},
"Microsoft.Extensions.Logging.Abstractions/10.0.2": {
"type": "package",
"serviceable": true,
"sha512": "sha512-RZkez/JjpnO+MZ6efKkSynN6ZztLpw3WbxNzjLCPBd97wWj1S9ZYPWi0nmT4kWBRa6atHsdM1ydGkUr8GudyDQ==",
"path": "microsoft.extensions.logging.abstractions/10.0.2",
"hashPath": "microsoft.extensions.logging.abstractions.10.0.2.nupkg.sha512"
},
"Microsoft.Extensions.Options/10.0.2": {
"type": "package",
"serviceable": true,
"sha512": "sha512-1De2LJjmxdqopI5AYC5dIhoZQ79AR5ayywxNF1rXrXFtKQfbQOV9+n/IsZBa7qWlr0MqoGpW8+OY2v/57udZOA==",
"path": "microsoft.extensions.options/10.0.2",
"hashPath": "microsoft.extensions.options.10.0.2.nupkg.sha512"
},
"Microsoft.Extensions.Primitives/10.0.2": {
"type": "package",
"serviceable": true,
"sha512": "sha512-QmSiO+oLBEooGgB3i0GRXyeYRDHjllqt3k365jwfZlYWhvSHA3UL2NEVV5m8aZa041eIlblo6KMI5txvTMpTwA==",
"path": "microsoft.extensions.primitives/10.0.2",
"hashPath": "microsoft.extensions.primitives.10.0.2.nupkg.sha512"
},
"Newtonsoft.Json/13.0.4": {
"type": "package",
"serviceable": true,
"sha512": "sha512-pdgNNMai3zv51W5aq268sujXUyx7SNdE2bj1wZcWjAQrKMFZV260lbqYop1d2GM67JI1huLRwxo9ZqnfF/lC6A==",
"path": "newtonsoft.json/13.0.4",
"hashPath": "newtonsoft.json.13.0.4.nupkg.sha512"
},
"SocketIOClient/4.0.0.2": {
"type": "package",
"serviceable": true,
"sha512": "sha512-RYtHafPCBCoY8F9KI583t4Dw3+c45XHmPf6xLIHtQeSimDLn3rMUSnITcCCRzbI7ITkKgw1eBhICdeVEs4hjHQ==",
"path": "socketioclient/4.0.0.2",
"hashPath": "socketioclient.4.0.0.2.nupkg.sha512"
},
"SocketIOClient.Common/4.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-7wlg0hMX5/k+fZejclVR7aKSj+Q37KCmVrKPIjZV+9z/odb11hZ4L+a0T3cV1w1jicTBWFEKvjWfWh6YKtz9Qg==",
"path": "socketioclient.common/4.0.0",
"hashPath": "socketioclient.common.4.0.0.nupkg.sha512"
},
"SocketIOClient.Serializer/4.0.0.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-+p1xnwSkX8UQQLgqr2Em6dIATl5pR7awHj1nbaRd/9aA2iAHGgy7HsseN8eblv3NHlPtTP9Y3IFDl5JKfWSYjg==",
"path": "socketioclient.serializer/4.0.0.1",
"hashPath": "socketioclient.serializer.4.0.0.1.nupkg.sha512"
},
"SocketIOClient.Serializer.NewtonsoftJson/4.0.0.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-D7nzYdIcNIPjGp7LW+KmJHk5I6uz3ioGb6fwxdpspuruwTTl1bTwczRuvEFcFjTHtb0Avhbcaw65jo6eAUmsYw==",
"path": "socketioclient.serializer.newtonsoftjson/4.0.0.1",
"hashPath": "socketioclient.serializer.newtonsoftjson.4.0.0.1.nupkg.sha512"
},
"System.Diagnostics.DiagnosticSource/10.0.2": {
"type": "package",
"serviceable": true,
"sha512": "sha512-lYWBy8fKkJHaRcOuw30d67PrtVjR5754sz5Wl76s8P+vJ9FSThh9b7LIcTSODx1LY7NB3Srvg+JMnzd67qNZOw==",
"path": "system.diagnostics.diagnosticsource/10.0.2",
"hashPath": "system.diagnostics.diagnosticsource.10.0.2.nupkg.sha512"
},
"System.IO.Pipelines/10.0.2": {
"type": "package",
"serviceable": true,
"sha512": "sha512-EqMsn9r18ABvTDxrDce4OWDhBE3y+rR23ilG7Y3BudDKrDKrLG/hkD/JmeFZbctAPxSkCjyJ/Ddwbn/g7ufRJA==",
"path": "system.io.pipelines/10.0.2",
"hashPath": "system.io.pipelines.10.0.2.nupkg.sha512"
},
"System.Text.Encodings.Web/10.0.2": {
"type": "package",
"serviceable": true,
"sha512": "sha512-Ro4cLT4qpRy64crfLAy3ekihtXckeXrD5eI6qb6NDSEVyHcHsmH7KgN4dbnIuiBmXIoaCslx4SynLYxag1SLSQ==",
"path": "system.text.encodings.web/10.0.2",
"hashPath": "system.text.encodings.web.10.0.2.nupkg.sha512"
},
"System.Text.Json/10.0.2": {
"type": "package",
"serviceable": true,
"sha512": "sha512-zy8ey7I16G9neZ6uzxrnYwS7pidElzN8XarsBjGu7lE2m7afTKMEe18KbY3ZSmh/z/bR40oxjd6hlUcmOEaMHw==",
"path": "system.text.json/10.0.2",
"hashPath": "system.text.json.10.0.2.nupkg.sha512"
}
}
}

View File

@ -1,12 +0,0 @@
{
"runtimeOptions": {
"tfm": "net8.0",
"framework": {
"name": "Microsoft.NETCore.App",
"version": "8.0.0"
},
"configProperties": {
"System.Runtime.Serialization.EnableUnsafeBinaryFormatterSerialization": false
}
}
}

View File

@ -1,82 +0,0 @@
{
"format": 1,
"restore": {
"C:\\Users\\mickl\\Desktop\\cliptrim-ui\\ClipTrimApp\\stream_deck_plugin\\ClientTest\\ClientTest.csproj": {}
},
"projects": {
"C:\\Users\\mickl\\Desktop\\cliptrim-ui\\ClipTrimApp\\stream_deck_plugin\\ClientTest\\ClientTest.csproj": {
"version": "1.0.0",
"restore": {
"projectUniqueName": "C:\\Users\\mickl\\Desktop\\cliptrim-ui\\ClipTrimApp\\stream_deck_plugin\\ClientTest\\ClientTest.csproj",
"projectName": "ClientTest",
"projectPath": "C:\\Users\\mickl\\Desktop\\cliptrim-ui\\ClipTrimApp\\stream_deck_plugin\\ClientTest\\ClientTest.csproj",
"packagesPath": "C:\\Users\\mickl\\.nuget\\packages\\",
"outputPath": "C:\\Users\\mickl\\Desktop\\cliptrim-ui\\ClipTrimApp\\stream_deck_plugin\\ClientTest\\obj\\",
"projectStyle": "PackageReference",
"fallbackFolders": [
"C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages"
],
"configFilePaths": [
"C:\\Users\\mickl\\AppData\\Roaming\\NuGet\\NuGet.Config",
"C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.FallbackLocation.config",
"C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.Offline.config"
],
"originalTargetFrameworks": [
"net8.0"
],
"sources": {
"C:\\Program Files (x86)\\Microsoft SDKs\\NuGetPackages\\": {},
"C:\\Program Files\\dotnet\\library-packs": {},
"https://api.nuget.org/v3/index.json": {},
"https://www.nuget.org/api/v2": {},
"https://www.nuget.org/api/v2": {}
},
"frameworks": {
"net8.0": {
"targetAlias": "net8.0",
"projectReferences": {}
}
},
"warningProperties": {
"warnAsError": [
"NU1605"
]
},
"restoreAuditProperties": {
"enableAudit": "true",
"auditLevel": "low",
"auditMode": "direct"
},
"SdkAnalysisLevel": "9.0.300"
},
"frameworks": {
"net8.0": {
"targetAlias": "net8.0",
"dependencies": {
"SocketIOClient": {
"target": "Package",
"version": "[4.0.0.2, )"
}
},
"imports": [
"net461",
"net462",
"net47",
"net471",
"net472",
"net48",
"net481"
],
"assetTargetFallback": true,
"warn": true,
"frameworkReferences": {
"Microsoft.NETCore.App": {
"privateAssets": "all"
}
},
"runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\9.0.307/PortableRuntimeIdentifierGraph.json"
}
}
}
}
}

View File

@ -1,16 +0,0 @@
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
<RestoreSuccess Condition=" '$(RestoreSuccess)' == '' ">True</RestoreSuccess>
<RestoreTool Condition=" '$(RestoreTool)' == '' ">NuGet</RestoreTool>
<ProjectAssetsFile Condition=" '$(ProjectAssetsFile)' == '' ">$(MSBuildThisFileDirectory)project.assets.json</ProjectAssetsFile>
<NuGetPackageRoot Condition=" '$(NuGetPackageRoot)' == '' ">$(UserProfile)\.nuget\packages\</NuGetPackageRoot>
<NuGetPackageFolders Condition=" '$(NuGetPackageFolders)' == '' ">C:\Users\mickl\.nuget\packages\;C:\Program Files (x86)\Microsoft Visual Studio\Shared\NuGetPackages</NuGetPackageFolders>
<NuGetProjectStyle Condition=" '$(NuGetProjectStyle)' == '' ">PackageReference</NuGetProjectStyle>
<NuGetToolVersion Condition=" '$(NuGetToolVersion)' == '' ">6.14.1</NuGetToolVersion>
</PropertyGroup>
<ItemGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
<SourceRoot Include="C:\Users\mickl\.nuget\packages\" />
<SourceRoot Include="C:\Program Files (x86)\Microsoft Visual Studio\Shared\NuGetPackages\" />
</ItemGroup>
</Project>

View File

@ -1,8 +0,0 @@
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ImportGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
<Import Project="$(NuGetPackageRoot)system.text.json\10.0.2\buildTransitive\net8.0\System.Text.Json.targets" Condition="Exists('$(NuGetPackageRoot)system.text.json\10.0.2\buildTransitive\net8.0\System.Text.Json.targets')" />
<Import Project="$(NuGetPackageRoot)microsoft.extensions.options\10.0.2\buildTransitive\net8.0\Microsoft.Extensions.Options.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.extensions.options\10.0.2\buildTransitive\net8.0\Microsoft.Extensions.Options.targets')" />
<Import Project="$(NuGetPackageRoot)microsoft.extensions.logging.abstractions\10.0.2\buildTransitive\net8.0\Microsoft.Extensions.Logging.Abstractions.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.extensions.logging.abstractions\10.0.2\buildTransitive\net8.0\Microsoft.Extensions.Logging.Abstractions.targets')" />
</ImportGroup>
</Project>

View File

@ -1,4 +0,0 @@
// <autogenerated />
using System;
using System.Reflection;
[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETCoreApp,Version=v8.0", FrameworkDisplayName = ".NET 8.0")]

View File

@ -1,23 +0,0 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
using System;
using System.Reflection;
[assembly: System.Reflection.AssemblyCompanyAttribute("ClientTest")]
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+8fda2a03af52202a841719b00041c255fbbd040b")]
[assembly: System.Reflection.AssemblyProductAttribute("ClientTest")]
[assembly: System.Reflection.AssemblyTitleAttribute("ClientTest")]
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
// Generated by the MSBuild WriteCodeFragment class.

View File

@ -1 +0,0 @@
b89f91df1271abd7a390167ccc0cd2ebdef3dc366236d6606664bbd406eb38f9

View File

@ -1,15 +0,0 @@
is_global = true
build_property.TargetFramework = net8.0
build_property.TargetPlatformMinVersion =
build_property.UsingMicrosoftNETSdkWeb =
build_property.ProjectTypeGuids =
build_property.InvariantGlobalization =
build_property.PlatformNeutralAssembly =
build_property.EnforceExtendedAnalyzerRules =
build_property._SupportedPlatformList = Linux,macOS,Windows
build_property.RootNamespace = ClientTest
build_property.ProjectDir = C:\Users\mickl\Desktop\cliptrim-ui\ClipTrimApp\stream_deck_plugin\ClientTest\
build_property.EnableComHosting =
build_property.EnableGeneratedComInterfaceComImportInterop =
build_property.EffectiveAnalysisLevelStyle = 8.0
build_property.EnableCodeStyleSeverity =

View File

@ -1,8 +0,0 @@
// <auto-generated/>
global using global::System;
global using global::System.Collections.Generic;
global using global::System.IO;
global using global::System.Linq;
global using global::System.Net.Http;
global using global::System.Threading;
global using global::System.Threading.Tasks;

View File

@ -1 +0,0 @@
1f0c38acb4d7bd17394bf7939e4ce787d1f5925df1475233861d85368fa71fee

View File

@ -1,32 +0,0 @@
C:\Users\mickl\Desktop\cliptrim-ui\ClipTrimApp\stream_deck_plugin\ClientTest\bin\Debug\net8.0\ClientTest.exe
C:\Users\mickl\Desktop\cliptrim-ui\ClipTrimApp\stream_deck_plugin\ClientTest\bin\Debug\net8.0\ClientTest.deps.json
C:\Users\mickl\Desktop\cliptrim-ui\ClipTrimApp\stream_deck_plugin\ClientTest\bin\Debug\net8.0\ClientTest.runtimeconfig.json
C:\Users\mickl\Desktop\cliptrim-ui\ClipTrimApp\stream_deck_plugin\ClientTest\bin\Debug\net8.0\ClientTest.dll
C:\Users\mickl\Desktop\cliptrim-ui\ClipTrimApp\stream_deck_plugin\ClientTest\bin\Debug\net8.0\ClientTest.pdb
C:\Users\mickl\Desktop\cliptrim-ui\ClipTrimApp\stream_deck_plugin\ClientTest\bin\Debug\net8.0\Microsoft.Extensions.DependencyInjection.dll
C:\Users\mickl\Desktop\cliptrim-ui\ClipTrimApp\stream_deck_plugin\ClientTest\bin\Debug\net8.0\Microsoft.Extensions.DependencyInjection.Abstractions.dll
C:\Users\mickl\Desktop\cliptrim-ui\ClipTrimApp\stream_deck_plugin\ClientTest\bin\Debug\net8.0\Microsoft.Extensions.Logging.dll
C:\Users\mickl\Desktop\cliptrim-ui\ClipTrimApp\stream_deck_plugin\ClientTest\bin\Debug\net8.0\Microsoft.Extensions.Logging.Abstractions.dll
C:\Users\mickl\Desktop\cliptrim-ui\ClipTrimApp\stream_deck_plugin\ClientTest\bin\Debug\net8.0\Microsoft.Extensions.Options.dll
C:\Users\mickl\Desktop\cliptrim-ui\ClipTrimApp\stream_deck_plugin\ClientTest\bin\Debug\net8.0\Microsoft.Extensions.Primitives.dll
C:\Users\mickl\Desktop\cliptrim-ui\ClipTrimApp\stream_deck_plugin\ClientTest\bin\Debug\net8.0\Newtonsoft.Json.dll
C:\Users\mickl\Desktop\cliptrim-ui\ClipTrimApp\stream_deck_plugin\ClientTest\bin\Debug\net8.0\SocketIOClient.dll
C:\Users\mickl\Desktop\cliptrim-ui\ClipTrimApp\stream_deck_plugin\ClientTest\bin\Debug\net8.0\SocketIOClient.Common.dll
C:\Users\mickl\Desktop\cliptrim-ui\ClipTrimApp\stream_deck_plugin\ClientTest\bin\Debug\net8.0\SocketIOClient.Serializer.dll
C:\Users\mickl\Desktop\cliptrim-ui\ClipTrimApp\stream_deck_plugin\ClientTest\bin\Debug\net8.0\SocketIOClient.Serializer.NewtonsoftJson.dll
C:\Users\mickl\Desktop\cliptrim-ui\ClipTrimApp\stream_deck_plugin\ClientTest\bin\Debug\net8.0\System.Diagnostics.DiagnosticSource.dll
C:\Users\mickl\Desktop\cliptrim-ui\ClipTrimApp\stream_deck_plugin\ClientTest\bin\Debug\net8.0\System.IO.Pipelines.dll
C:\Users\mickl\Desktop\cliptrim-ui\ClipTrimApp\stream_deck_plugin\ClientTest\bin\Debug\net8.0\System.Text.Encodings.Web.dll
C:\Users\mickl\Desktop\cliptrim-ui\ClipTrimApp\stream_deck_plugin\ClientTest\bin\Debug\net8.0\System.Text.Json.dll
C:\Users\mickl\Desktop\cliptrim-ui\ClipTrimApp\stream_deck_plugin\ClientTest\bin\Debug\net8.0\runtimes\browser\lib\net8.0\System.Text.Encodings.Web.dll
C:\Users\mickl\Desktop\cliptrim-ui\ClipTrimApp\stream_deck_plugin\ClientTest\obj\Debug\net8.0\ClientTest.csproj.AssemblyReference.cache
C:\Users\mickl\Desktop\cliptrim-ui\ClipTrimApp\stream_deck_plugin\ClientTest\obj\Debug\net8.0\ClientTest.GeneratedMSBuildEditorConfig.editorconfig
C:\Users\mickl\Desktop\cliptrim-ui\ClipTrimApp\stream_deck_plugin\ClientTest\obj\Debug\net8.0\ClientTest.AssemblyInfoInputs.cache
C:\Users\mickl\Desktop\cliptrim-ui\ClipTrimApp\stream_deck_plugin\ClientTest\obj\Debug\net8.0\ClientTest.AssemblyInfo.cs
C:\Users\mickl\Desktop\cliptrim-ui\ClipTrimApp\stream_deck_plugin\ClientTest\obj\Debug\net8.0\ClientTest.csproj.CoreCompileInputs.cache
C:\Users\mickl\Desktop\cliptrim-ui\ClipTrimApp\stream_deck_plugin\ClientTest\obj\Debug\net8.0\ClientTest.csproj.Up2Date
C:\Users\mickl\Desktop\cliptrim-ui\ClipTrimApp\stream_deck_plugin\ClientTest\obj\Debug\net8.0\ClientTest.dll
C:\Users\mickl\Desktop\cliptrim-ui\ClipTrimApp\stream_deck_plugin\ClientTest\obj\Debug\net8.0\refint\ClientTest.dll
C:\Users\mickl\Desktop\cliptrim-ui\ClipTrimApp\stream_deck_plugin\ClientTest\obj\Debug\net8.0\ClientTest.pdb
C:\Users\mickl\Desktop\cliptrim-ui\ClipTrimApp\stream_deck_plugin\ClientTest\obj\Debug\net8.0\ClientTest.genruntimeconfig.cache
C:\Users\mickl\Desktop\cliptrim-ui\ClipTrimApp\stream_deck_plugin\ClientTest\obj\Debug\net8.0\ref\ClientTest.dll

Some files were not shown because too many files have changed in this diff Show More