Skip to content
Permalink
Browse files

feat: add Winamp

* feat: prevent redundant update

* feat: custom header

* test webamp

* add webamp

* feat: add Winamp

* webamp beta for dispose
  • Loading branch information...
ShizukuIchi committed Apr 4, 2019
1 parent 1dad5a0 commit 4ba5fd1ed34ab627fdbb2c4254f2e1cd81c30dee
@@ -1,19 +1,19 @@
# [WinXP](https://winxp.now.sh)
# WinXP

🏁 Web based Windows XP desktop recreation.

Features:

- Drag and resize, minimize, maximize windows
- Open applications from desktop icons or start menu
- Minesweeper, Internet Explorer, My Computer, Notepad
- Minesweeper, Internet Explorer, My Computer, Notepad, Winamp
- Power off menu

## Try it!
## [Try it!](https://winxp.now.sh)

Windows XP πŸ‘‰ https://winxp.now.sh

![](demo/demo.gif)
[![](demo/demo.gif)](https://winxp.now.sh)

## Contributing

@@ -22,3 +22,6 @@ Generally open an issue (or comment on an issue if there's one already) before s
## License

The Windows XP name, artwork, trademark are surely property of Microsoft. This project is provided for educational purposes only. It is not affiliated with and has not been approved by Microsoft.

## Thanks
- [Webamp](https://github.com/captbaritone/webamp), Winamp 2 reimplementation by: [captbaritone](https://github.com/captbaritone)
@@ -11,7 +11,8 @@
"react-ga": "^2.5.7",
"react-scripts": "2.1.8",
"react-use": "^7.0.1",
"styled-components": "^4.2.0"
"styled-components": "^4.2.0",
"webamp": "^1.3.2-beta.2"
},
"scripts": {
"start": "react-scripts start",
@@ -7,8 +7,6 @@ import outlook from 'src/assets/windowsIcons/887(32x32).png';
import mediaPlayer from 'src/assets/windowsIcons/846(32x32).png';
import messenger from 'src/assets/windowsIcons/msn.png';
import tour from 'src/assets/windowsIcons/853(32x32).png';
import transfer from 'src/assets/windowsIcons/367(32x32).png';
import calculator from 'src/assets/windowsIcons/74(32x32).png';
import documents from 'src/assets/windowsIcons/308(32x32).png';
import recentDocuments from 'src/assets/windowsIcons/301(32x32).png';
import pictures from 'src/assets/windowsIcons/307(32x32).png';
@@ -24,6 +22,8 @@ import lock from 'src/assets/windowsIcons/546(32x32).png';
import user from 'src/assets/windowsIcons/user.png';
import shut from 'src/assets/windowsIcons/310(32x32).png';
import allProgramsIcon from 'src/assets/windowsIcons/all-programs.ico';
import winamp from 'src/assets/windowsIcons/winamp.png';
import notepad from 'src/assets/windowsIcons/327(32x32).png';

import empty from 'src/assets/empty.png';

@@ -58,11 +58,11 @@ function FooterMenu({ className, onClick }) {
onClick={onClick}
items={[
{ icon: mine, text: 'Minesweeper' },
{ icon: notepad, text: 'Notepad' },
{ icon: winamp, text: 'Winamp' },
{ icon: mediaPlayer, text: 'Windows Media Player' },
{ icon: messenger, text: 'Windows Messenger' },
{ icon: tour, text: 'Tour Windows XP' },
{ icon: transfer, text: 'Files and Settings Transfer Wizard' },
{ icon: calculator, text: 'Calculator' },
]}
/>
<div style={{ flex: 1 }} />
@@ -50,7 +50,7 @@ function Footer({
useEffect(() => {
const timer = setInterval(() => {
const newTime = getTime();
newTime !== time && setTime(getTime());
newTime !== time && setTime(newTime);
}, 1000);
return () => clearInterval(timer);
}, []);
@@ -82,8 +82,8 @@ function Footer({
<FooterWindow
key={app.id}
id={app.id}
icon={app.headerIcon}
title={app.title}
icon={app.header.icon}
title={app.header.title}
onMouseDown={onMouseDownApp}
isFocus={focusedAppId === app.id}
/>
@@ -89,8 +89,8 @@ function Icon({

const IconsContainer = styled.div`
position: absolute;
margin-top: 60px;
margin-left: 60px;
margin-top: 40px;
margin-left: 40px;
`;

const StyledIcon = styled(Icon)`
@@ -1,4 +1,4 @@
import React, { useRef } from 'react';
import React, { useRef, memo } from 'react';
import useWindowSize from 'react-use/lib/useWindowSize';
import { useElementResize } from 'src/hooks';
import styled from 'styled-components';
@@ -20,27 +20,25 @@ function Windows({
onMouseUpClose={onClose}
onMouseUpMinimize={onMinimize}
onMouseUpMaximize={onMaximize}
isFocus={focusedAppId === app.id}
isFocus={focusedAppId === app.id} // for styledWindow
{...app}
>
<app.component onClose={onClose.bind(null, app.id)} />
</StyledWindow>
/>
));
}

function Window({
children,
const Window = memo(function({
insertProps,
id,
onMouseDown,
onMouseUpClose,
onMouseUpMinimize,
onMouseUpMaximize,
title,
header,
defaultSize,
defaultOffset,
resizable,
headerIcon,
maximized,
component,
className,
}) {
function _onMouseDown() {
@@ -96,8 +94,12 @@ function Window({
>
<div className="header__bg" />
<header className="app__header" ref={dragRef}>
<img src={headerIcon} alt={title} className="app__header__icon" />
<div className="app__header__title">{title}</div>
<img
src={header.icon}
alt={header.title}
className="app__header__icon"
/>
<div className="app__header__title">{header.title}</div>
<div className="app__header__buttons">
<button
className="app__header__minimize"
@@ -112,15 +114,22 @@ function Window({
<button className="app__header__close" onMouseUp={_onMouseUpClose} />
</div>
</header>
<div className="app__content">{children}</div>
<div className="app__content">
{component({
onClose: _onMouseUpClose,
onMinimize: _onMouseUpMinimize,
...insertProps,
})}
</div>
</div>
);
}
});

const StyledWindow = styled(Window)`
display: ${({ show }) => (show ? 'flex' : 'none')};
position: absolute;
padding: 3px;
padding: ${({ header }) => (header.disable ? 0 : 3)}px;
background-color: ${({ isFocus }) => (isFocus ? '#0831d9' : '#6582f5')};
flex-direction: column;
border-top-left-radius: 8px;
@@ -163,6 +172,7 @@ const StyledWindow = styled(Window)`
width: 15px;
}
.app__header {
display: ${({ header }) => (header.disable ? 'none' : 'flex')};
height: 25px;
line-height: 25px;
font-weight: 700;
@@ -173,7 +183,6 @@ const StyledWindow = styled(Window)`
position: absolute;
left: 3px;
right: 3px;
display: flex;
align-items: center;
}
.app__header__icon {
@@ -3,9 +3,9 @@ import styled from 'styled-components';

import error from 'src/assets/windowsIcons/897(32x32).png';

function Error({ onClose, className }) {
function Error({ onClose }) {
return (
<div className={className}>
<Div>
<div className="error__top">
<img src={error} alt="error" className="error__img" />
<div className="error__messages">
@@ -18,11 +18,11 @@ function Error({ onClose, className }) {
<span>OK</span>
</div>
</div>
</div>
</Div>
);
}

export default styled(Error)`
const Div = styled.div`
background-color: #f5f5f5;
width: 100%;
height: 100%;
@@ -64,3 +64,5 @@ export default styled(Error)`
}
}
`;

export default Error;
@@ -0,0 +1,126 @@
// from Webamp demo

const album = 'netBloc Vol. 24: tiuqottigeloot';

export const initialTracks = [
{
url:
'https://raw.githubusercontent.com/captbaritone/webamp-music/4b556fbf/Diablo_Swing_Orchestra_-_01_-_Heroines.mp3',
duration: 322.612245,
metaData: {
title: 'Heroines',
artist: 'Diablo Swing Orchestra',
album,
},
},
{
url:
'https://raw.githubusercontent.com/captbaritone/webamp-music/4b556fbf/Eclectek_-_02_-_We_Are_Going_To_Eclecfunk_Your_Ass.mp3',
duration: 190.093061,
metaData: {
title: 'We Are Going To Eclecfunk Your Ass',
artist: 'Eclectek',
album,
},
},
{
url:
'https://raw.githubusercontent.com/captbaritone/webamp-music/4b556fbf/Auto-Pilot_-_03_-_Seventeen.mp3',
duration: 214.622041,
metaData: {
title: 'Seventeen',
artist: 'Auto-Pilot',
album,
},
},
{
url:
'https://raw.githubusercontent.com/captbaritone/webamp-music/4b556fbf/Muha_-_04_-_Microphone.mp3',
duration: 181.838367,
metaData: {
title: 'Microphone',
artist: 'Muha',
album,
},
},
{
url:
'https://raw.githubusercontent.com/captbaritone/webamp-music/4b556fbf/Just_Plain_Ant_-_05_-_Stumble.mp3',
duration: 86.047347,
metaData: {
title: 'Stumble',
artist: 'Just Plain Ant',
album,
},
},
{
url:
'https://raw.githubusercontent.com/captbaritone/webamp-music/4b556fbf/Sleaze_-_06_-_God_Damn.mp3',
duration: 226.795102,
metaData: {
title: 'God Damn',
artist: 'Sleaze',
album,
},
},
{
url:
'https://raw.githubusercontent.com/captbaritone/webamp-music/4b556fbf/Juanitos_-_07_-_Hola_Hola_Bossa_Nova.mp3',
duration: 207.072653,
metaData: {
title: 'Hola Hola Bossa Nova',
artist: 'Juanitos',
album,
},
},
{
url:
'https://raw.githubusercontent.com/captbaritone/webamp-music/4b556fbf/Entertainment_for_the_Braindead_-_08_-_Resolutions_Chris_Summer_Remix.mp3',
duration: 314.331429,
metaData: {
title: 'Resolutions (Chris Summer Remix)',
artist: 'Entertainment for the Braindead',
album,
},
},
{
url:
'https://raw.githubusercontent.com/captbaritone/webamp-music/4b556fbf/Nobara_Hayakawa_-_09_-_Trail.mp3',
duration: 204.042449,
metaData: {
title: 'Trail',
artist: 'Nobara Hayakawa',
album,
},
},
{
url:
'https://raw.githubusercontent.com/captbaritone/webamp-music/4b556fbf/Paper_Navy_-_10_-_Tongue_Tied.mp3',
duration: 201.116735,
metaData: {
title: 'Tongue Tied',
artist: 'Paper Navy',
album,
},
},
{
url:
'https://raw.githubusercontent.com/captbaritone/webamp-music/4b556fbf/60_Tigres_-_11_-_Garage.mp3',
duration: 245.394286,
metaData: {
title: 'Garage',
artist: '60 Tigres',
album,
},
},
{
url:
'https://raw.githubusercontent.com/captbaritone/webamp-music/4b556fbf/CM_aka_Creative_-_12_-_The_Cycle_Featuring_Mista_Mista.mp3',
duration: 221.44,
metaData: {
title: 'The Cycle (Featuring Mista Mista)',
artist: 'CM aka Creative',
album,
},
},
];
@@ -0,0 +1,37 @@
import React, { useEffect, useRef } from 'react';
import Webamp from 'webamp';
import { initialTracks } from './config';

function Winamp({ onClose, onMinimize }) {
const ref = useRef(null);
const webamp = useRef(null);
useEffect(() => {
const target = ref.current;
if (!target) {
return;
}
webamp.current = new Webamp({
initialTracks,
});
webamp.current.renderWhenReady(target).then(() => {
target.appendChild(document.querySelector('#webamp'));
});
return () => {
webamp.current.dispose();
};
}, []);
useEffect(() => {
if (webamp.current) {
webamp.current.onClose(onClose);
webamp.current.onMinimize(onMinimize);
}
});
return (
<div
style={{ position: 'fixed', left: 0, top: 0, right: 0, bottom: 0 }}
ref={ref}
/>
);
}

export default Winamp;
Oops, something went wrong.

1 comment on commit 4ba5fd1

@now

This comment has been minimized.

Copy link

now bot commented on 4ba5fd1 Apr 4, 2019

Please sign in to comment.
You can’t perform that action at this time.