Skip to content

Commit cf869f2

Browse files
committed
chore: release v0.4.5
1 parent b55ba85 commit cf869f2

14 files changed

Lines changed: 263 additions & 468 deletions

RELEASE_NOTES.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,16 @@
1+
# Playerr v0.4.5 - The Connected Update 🔌
2+
This release introduces advanced hardware connectivity features and expands platform support.
3+
4+
### ⚡ Advanced USB Protocol
5+
* **Direct Hardware Transfer**: Implemented a robust USB transfer system allowing direct installation to connected devices.
6+
* **Smart Permissions**: Improved USB handling on macOS to gracefully handle permission denied errors without requiring root access.
7+
* **Protocol Integrity**: Enhanced handshake and error handling to ensure data integrity during transfers.
8+
* **Credits**: Implementation based on the excellent work by `rashevskyv/dbi`.
9+
10+
### 🛠️ Improvements
11+
* **UI/UX**: Added "Close Anyway" option for modal dialogs to prevent UI lockups.
12+
* **Platform Detection**: Refined logic for hiding irrelevant actions (Play/Install) on specific platforms.
13+
114
# Playerr v0.4.4 - The Cleanup & Scanner Update 🧹
215
This release focuses on scanning accuracy, Wine/Whisky integration, and security improvements for Linux.
316

build_all.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
set -e
33

44
# Define version
5-
VERSION="0.4.4"
5+
VERSION="0.4.5"
66
OUTPUT_DIR="build_artifacts"
77

88
echo "=================================="

build_mac_only.sh

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ echo "=================================="
1111
echo "[1/3] Building Frontend..."
1212
npm run build
1313

14+
# 2. Publish Backend for macOS (ARM64 default for this user)
1415
# 2. Publish Backend for macOS (ARM64 default for this user)
1516
echo "[2/3] Publishing Backend (OSX-ARM64)..."
1617
dotnet publish src/Playerr.Host/Playerr.Host.csproj \
@@ -20,6 +21,18 @@ dotnet publish src/Playerr.Host/Playerr.Host.csproj \
2021
-p:PublishSingleFile=false \
2122
-o build_artifacts/osx-arm64
2223

24+
echo " Publishing UsbHelper..."
25+
dotnet publish src/Playerr.UsbHelper/Playerr.UsbHelper.csproj \
26+
-c Release \
27+
-r osx-arm64 \
28+
--self-contained true \
29+
-p:PublishSingleFile=false \
30+
-o build_artifacts/osx-arm64
31+
32+
echo " Copying Python Helper..."
33+
cp src/Playerr.Core/Switch/SwitchUsbHelper.py build_artifacts/osx-arm64/
34+
35+
2336
# 3. Create .app Bundle
2437
echo "[3/3] Packaging .app (with Icon & Launcher)..."
2538
APP_NAME="build_artifacts/Playerr"

create_mac_app.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ cat > "$APP_BUNDLE/Contents/Info.plist" <<EOF
5858
<key>CFBundleIdentifier</key>
5959
<string>app.playerr.desktop</string>
6060
<key>CFBundleVersion</key>
61-
<string>0.4.2</string>
61+
<string>0.4.5</string>
6262
<key>CFBundlePackageType</key>
6363
<string>APPL</string>
6464
<key>CFBundleExecutable</key>

frontend/src/components/SwitchInstallerModal.tsx

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,6 @@ const SwitchInstallerModal: React.FC<SwitchInstallerModalProps> = ({ isOpen, onC
3030
}, [isOpen]);
3131

3232
const handleClose = async () => {
33-
if (isInstalling) {
34-
try {
35-
await axios.post('/api/v3/nsw/cancel');
36-
} catch (e) {
37-
console.error('Cancel error:', e);
38-
}
39-
}
4033
onClose();
4134
};
4235

frontend/src/i18n/translations.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -542,10 +542,11 @@ export const translations = {
542542
plat_macos: 'macOS',
543543
plat_retro: 'Retro / Emulation',
544544
// About Content
545-
aboutMainDesc: 'Playerr is an open-source media manager designed to centralize, organize, and automate your video game collection on any platform.',
545+
aboutMainDesc: 'Playerr is an open-source media manager designed to centralize, organize, and automate your video game collection on any platform. Special thanks to rashevskyv/dbi for the USB transfer protocols.',
546546
featuresTitle: 'Features',
547547
featureScanning: 'Library scanning engine',
548548
featureIntegration: 'Native integration with Steam, IGDB, qBittorrent, and Prowlarr',
549+
featureUsb: 'Advanced USB file transfer and management (DBI Protocol)',
549550
featureCrossPlatform: 'Project in development for Linux, Windows, macOS, and Docker',
550551
roadmapTitle: 'In Development',
551552
roadmapBazzite: 'In Progress: Studying compatibility with Lutris and Proton on Bazzite.',

frontend/src/pages/About.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ const About: React.FC = () => {
6565
<div onClick={toggleKofi} style={{ cursor: 'pointer', display: 'inline-block' }}>
6666
<img src={appLogo} alt="Playerr" style={{ width: '100px', height: 'auto', marginBottom: '0.75rem' }} />
6767
</div>
68-
<h3>Playerr v0.4.4</h3>
68+
<h3>Playerr v0.4.5</h3>
6969
</div>
7070

7171
<div className="settings-section" style={{ border: 'none', padding: 0, backgroundColor: 'transparent' }}>
@@ -79,6 +79,7 @@ const About: React.FC = () => {
7979
<ul style={{ listStyleType: 'none', padding: 0, color: '#a6adc8', lineHeight: '1.6', fontSize: '0.9rem' }}>
8080
<li>{t('featureScanning')}</li>
8181
<li>{t('featureIntegration')}</li>
82+
<li>{t('featureUsb')}</li>
8283
<li>{t('featureCrossPlatform')}</li>
8384
</ul>
8485
</div>
@@ -87,7 +88,7 @@ const About: React.FC = () => {
8788
<h4 style={{ color: '#cdd6f4', fontSize: '1rem', marginBottom: '0.75rem', fontWeight: 600 }}>{t('roadmapTitle')}</h4>
8889
<ul style={{ listStyleType: 'none', padding: 0, color: '#a6adc8', lineHeight: '1.6', fontSize: '0.9rem' }}>
8990
<li>{t('roadmapBazzite')}</li>
90-
<li>{t('roadmapUsb')}</li>
91+
{/* <li>• {t('roadmapUsb')} (Completed v0.4.5)</li> */}
9192
<li>{t('roadmapAppStores')}</li>
9293
<li>{t('roadmapExtensibility')}</li>
9394
</ul>

frontend/src/pages/GameDetails.tsx

Lines changed: 39 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -490,6 +490,14 @@ const GameDetails: React.FC = () => {
490490
);
491491
}
492492

493+
const isSwitchGame = (() => {
494+
if (!game) return false;
495+
const pathLower = game.path?.toLowerCase() || '';
496+
const isSwitchFile = pathLower.endsWith('.nsp') || pathLower.endsWith('.xci') || pathLower.endsWith('.nsz') || pathLower.endsWith('.xcz');
497+
const isSwitchPlatform = game.platform?.name?.toLowerCase().includes('switch') || false;
498+
return isSwitchFile || isSwitchPlatform;
499+
})();
500+
493501
return (
494502
<div className="game-details">
495503
<div className="game-details-header">
@@ -535,45 +543,39 @@ const GameDetails: React.FC = () => {
535543
<span>{t('remove')}</span>
536544
</button>
537545

538-
<button
539-
className={`action-btn ${game.isInstallable && !game.canPlay ? 'install-ready' : ''}`}
540-
onClick={handleInstallClick}
541-
title={t('install')}
542-
>
543-
<FontAwesomeIcon icon={faDownload} />
544-
<span>{t('install')}</span>
545-
</button>
546-
547-
{(() => {
548-
if (!game.path) return null;
549-
const pathLower = game.path.toLowerCase();
550-
const isSwitchFile = pathLower.endsWith('.nsp') || pathLower.endsWith('.xci') || pathLower.endsWith('.nsz') || pathLower.endsWith('.xcz');
551-
const isSwitchPlatform = game.platform?.name.includes('Switch');
546+
{(!isSwitchGame) && (
547+
<button
548+
className={`action-btn ${game.isInstallable && !game.canPlay ? 'install-ready' : ''}`}
549+
onClick={handleInstallClick}
550+
title={t('install')}
551+
>
552+
<FontAwesomeIcon icon={faDownload} />
553+
<span>{t('install')}</span>
554+
</button>
555+
)}
552556

553-
if (isSwitchFile || isSwitchPlatform) {
554-
return (
555-
<button
556-
className="action-btn switch-usb"
557-
onClick={() => setShowSwitchModal(true)}
558-
title="Install to Switch via USB"
559-
style={{ background: '#e60012', color: 'white' }}
560-
>
561-
<FontAwesomeIcon icon={faMicrochip} />
562-
<span>USB Install</span>
563-
</button>
564-
);
565-
}
566-
return null;
567-
})()}
557+
{isSwitchGame && (
558+
<button
559+
className="action-btn switch-usb"
560+
onClick={() => setShowSwitchModal(true)}
561+
title="Install to Switch via USB"
562+
style={{ background: '#e60012', color: 'white' }}
563+
>
564+
<FontAwesomeIcon icon={faMicrochip} />
565+
<span>USB Install</span>
566+
</button>
567+
)}
568568

569-
<button
570-
className={`action-btn ${game.canPlay ? 'play-ready' : ''}`}
571-
onClick={handlePlay}
572-
title={t('play')}
573-
>
574-
<FontAwesomeIcon icon={faGamepad} />
575-
<span>{t('play')}</span>
576-
</button>
569+
{(!isSwitchGame) && (
570+
<button
571+
className={`action-btn ${game.canPlay ? 'play-ready' : ''}`}
572+
onClick={handlePlay}
573+
title={t('play')}
574+
>
575+
<FontAwesomeIcon icon={faGamepad} />
576+
<span>{t('play')}</span>
577+
</button>
578+
)}
577579
</div>
578580
<div className="meta">
579581
<span>{game.year}</span>

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "playerr",
3-
"version": "0.4.4",
3+
"version": "0.4.5",
44
"description": "Playerr - A PVR for Video Games",
55
"scripts": {
66
"build": "webpack --config ./frontend/build/webpack.config.js",

src/Directory.Build.props

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@
6868
<Copyright>Copyright 2025-$([System.DateTime]::Now.ToString('yyyy')) playerr.app</Copyright>
6969

7070
<!-- Should be replaced by CI -->
71-
<AssemblyVersion>0.4.4</AssemblyVersion>
71+
<AssemblyVersion>0.4.5</AssemblyVersion>
7272
<AssemblyConfiguration>$(Configuration)-dev</AssemblyConfiguration>
7373
<NeutralLanguage>en</NeutralLanguage>
7474

0 commit comments

Comments
 (0)