diff --git a/pages/etcetera.php b/pages/etcetera.php index a7338a8..ffc9284 100644 --- a/pages/etcetera.php +++ b/pages/etcetera.php @@ -34,6 +34,11 @@ if($reqPath === '/etc') { 'desc' => 'Generates a number of random keys at various lengths using a secure random number generator.', 'link' => '//flash.moe/key.php', ], + [ + 'title' => 'Forum Archive', + 'desc' => 'Temporary archive of the flash.moe message board.', + 'link' => '//forum.flash.moe', + ], [ 'title' => 'The Abyss', 'desc' => 'Accumulated collection of historical trash. Beware that the things here are unaltered products of their time.', diff --git a/pages/index.php b/pages/index.php index 0352cfb..7e2e399 100644 --- a/pages/index.php +++ b/pages/index.php @@ -115,6 +115,11 @@ if($reqPath === '/test') { return FM_HIT; } +if($reqPath === '/donate') { + header('Location: https://paypal.me/flashwave'); + return FM_HIT | 302; +} + if($reqPath === '/') { if($reqMethod !== 'GET') return FM_ERR | 405; diff --git a/public/fortknif.mp4 b/public/fortknif.mp4 new file mode 100644 index 0000000..bba1c37 Binary files /dev/null and b/public/fortknif.mp4 differ diff --git a/public/fwif/index.html b/public/fwif/index.html new file mode 100644 index 0000000..ab4e6a3 --- /dev/null +++ b/public/fwif/index.html @@ -0,0 +1,11 @@ + + + + + FWIF Specification + + +

FWIF Specification

+

FWIF (Flashwave's Interchange Format) is a

+ + diff --git a/public/index.php b/public/index.php index 07d3889..f72a674 100644 --- a/public/index.php +++ b/public/index.php @@ -10,7 +10,7 @@ define('FM_NAV', [ ['title' => 'Contact', 'link' => '/contact'], ['title' => 'Related', 'link' => '/related'], ['title' => 'Etcetera', 'link' => '/etc'], - ['title' => 'Forum', 'link' => '//forum.flash.moe'], + //['title' => 'Forum', 'link' => '//forum.flash.moe'], ]); define('FM_BGS', [ diff --git a/public/mpv.php b/public/mpv.php index aa2b8a4..c072779 100644 --- a/public/mpv.php +++ b/public/mpv.php @@ -8,5 +8,5 @@ if(isset($_GET['source'])) { ">Open in MPV diff --git a/public/player/flashplayer32_0r0_363_linux.i386.tar.gz b/public/player/flashplayer32_0r0_363_linux.i386.tar.gz new file mode 100644 index 0000000..7f95430 Binary files /dev/null and b/public/player/flashplayer32_0r0_363_linux.i386.tar.gz differ diff --git a/public/player/flashplayer32_0r0_363_linux.x86_64.tar.gz b/public/player/flashplayer32_0r0_363_linux.x86_64.tar.gz new file mode 100644 index 0000000..509eaa9 Binary files /dev/null and b/public/player/flashplayer32_0r0_363_linux.x86_64.tar.gz differ diff --git a/public/player/flashplayer32_0r0_363_linux_sa.x86_64.tar.gz b/public/player/flashplayer32_0r0_363_linux_sa.x86_64.tar.gz new file mode 100644 index 0000000..9e2b0e5 Binary files /dev/null and b/public/player/flashplayer32_0r0_363_linux_sa.x86_64.tar.gz differ diff --git a/public/player/flashplayer32_0r0_363_linuxpep.i386.tar.gz b/public/player/flashplayer32_0r0_363_linuxpep.i386.tar.gz new file mode 100644 index 0000000..0b3fd10 Binary files /dev/null and b/public/player/flashplayer32_0r0_363_linuxpep.i386.tar.gz differ diff --git a/public/player/flashplayer32_0r0_363_linuxpep.x86_64.tar.gz b/public/player/flashplayer32_0r0_363_linuxpep.x86_64.tar.gz new file mode 100644 index 0000000..a53795b Binary files /dev/null and b/public/player/flashplayer32_0r0_363_linuxpep.x86_64.tar.gz differ diff --git a/public/player/flashplayer32_0r0_363_mac.dmg b/public/player/flashplayer32_0r0_363_mac.dmg new file mode 100644 index 0000000..36723ec Binary files /dev/null and b/public/player/flashplayer32_0r0_363_mac.dmg differ diff --git a/public/player/flashplayer32_0r0_363_mac_pkg.dmg b/public/player/flashplayer32_0r0_363_mac_pkg.dmg new file mode 100644 index 0000000..d417ebd Binary files /dev/null and b/public/player/flashplayer32_0r0_363_mac_pkg.dmg differ diff --git a/public/player/flashplayer32_0r0_363_mac_sa.dmg b/public/player/flashplayer32_0r0_363_mac_sa.dmg new file mode 100644 index 0000000..a23e286 Binary files /dev/null and b/public/player/flashplayer32_0r0_363_mac_sa.dmg differ diff --git a/public/player/flashplayer32_0r0_363_macpep.dmg b/public/player/flashplayer32_0r0_363_macpep.dmg new file mode 100644 index 0000000..5c43724 Binary files /dev/null and b/public/player/flashplayer32_0r0_363_macpep.dmg differ diff --git a/public/player/flashplayer32_0r0_363_macpep_pkg.dmg b/public/player/flashplayer32_0r0_363_macpep_pkg.dmg new file mode 100644 index 0000000..e17b473 Binary files /dev/null and b/public/player/flashplayer32_0r0_363_macpep_pkg.dmg differ diff --git a/public/player/flashplayer32_0r0_363_win.msi b/public/player/flashplayer32_0r0_363_win.msi new file mode 100644 index 0000000..1178d68 Binary files /dev/null and b/public/player/flashplayer32_0r0_363_win.msi differ diff --git a/public/player/flashplayer32_0r0_363_win_sa.exe b/public/player/flashplayer32_0r0_363_win_sa.exe new file mode 100644 index 0000000..5571d06 Binary files /dev/null and b/public/player/flashplayer32_0r0_363_win_sa.exe differ diff --git a/public/player/flashplayer32_0r0_363_winax.msi b/public/player/flashplayer32_0r0_363_winax.msi new file mode 100644 index 0000000..f804af0 Binary files /dev/null and b/public/player/flashplayer32_0r0_363_winax.msi differ diff --git a/public/player/flashplayer32_0r0_363_winpep.msi b/public/player/flashplayer32_0r0_363_winpep.msi new file mode 100644 index 0000000..1d2d7e0 Binary files /dev/null and b/public/player/flashplayer32_0r0_363_winpep.msi differ diff --git a/public/player/uninstall_flashplayer32_0r0_363_mac.dmg b/public/player/uninstall_flashplayer32_0r0_363_mac.dmg new file mode 100644 index 0000000..a19a47f Binary files /dev/null and b/public/player/uninstall_flashplayer32_0r0_363_mac.dmg differ diff --git a/public/player/uninstall_flashplayer32_0r0_363_win.exe b/public/player/uninstall_flashplayer32_0r0_363_win.exe new file mode 100644 index 0000000..021f657 Binary files /dev/null and b/public/player/uninstall_flashplayer32_0r0_363_win.exe differ diff --git a/public/topmostfriend/_inc/out.php b/public/topmostfriend/_inc/out.php new file mode 100644 index 0000000..1181a41 --- /dev/null +++ b/public/topmostfriend/_inc/out.php @@ -0,0 +1,72 @@ + [ + 'href' => './', + 'text' => 'Home', + ], + 'downloads' => [ + 'href' => './downloads.php', + 'text' => 'Downloads', + ], + 'changelog' => [ + 'href' => './changelog.php', + 'text' => 'Changelog', + ], + 'repository' => [ + 'href' => 'https://github.com/flashwave/topmostfriend', + 'text' => 'Repository', + ], + 'donate' => [ + 'href' => '//flash.moe/donate', + 'text' => 'Donate', + ], + ]; +?> + + + + + <?=(empty($title) ? '' : ($title . ' :: '));?>Top Most Friend + + + + + + + +
+
+
+ $info): ?> + > + +
+ +
+
+
+ © flashwave 2020- +
+
+ + + diff --git a/public/topmostfriend/about.jpg b/public/topmostfriend/about.jpg new file mode 100644 index 0000000..5157037 Binary files /dev/null and b/public/topmostfriend/about.jpg differ diff --git a/public/topmostfriend/arrow_refresh.gif b/public/topmostfriend/arrow_refresh.gif new file mode 100644 index 0000000..312c00d Binary files /dev/null and b/public/topmostfriend/arrow_refresh.gif differ diff --git a/public/topmostfriend/changelog.php b/public/topmostfriend/changelog.php new file mode 100644 index 0000000..67d97ea --- /dev/null +++ b/public/topmostfriend/changelog.php @@ -0,0 +1,40 @@ +{$title}" + . "{$indent}

{$description}

"; + +foreach($files as $fileName) { + $file = fopen($fileName, 'rb'); + $header = trim(fgets($file)); + if(empty($header)) + continue; + + [$version, $date] = explode(' - ', $header, 2); + $versionId = $version; + $date = strtotime($date); + + $body .= sprintf('%s

%s —

', $indent, $versionId, $versionId, $version, date('c', $date), date('Y-m-d', $date)); + + while(($line = fgets($file)) !== false) { + $line = trim($line); + if(empty($line)) + continue; + + [$stamp, $line] = explode(' ', $line, 2); + + $body .= sprintf('%s

%s %s

', $indent, $stamp, $line); + } + + fclose($file); +} + +$body .= substr($indent, 0, -4); + +require_once __DIR__ . '/_inc/out.php'; diff --git a/public/topmostfriend/cog.gif b/public/topmostfriend/cog.gif new file mode 100644 index 0000000..2b50c16 Binary files /dev/null and b/public/topmostfriend/cog.gif differ diff --git a/public/topmostfriend/dl/v1.0.0/TopMostFriend.exe b/public/topmostfriend/dl/v1.0.0/TopMostFriend.exe new file mode 100644 index 0000000..fdc2645 Binary files /dev/null and b/public/topmostfriend/dl/v1.0.0/TopMostFriend.exe differ diff --git a/public/topmostfriend/dl/v1.0.0/TopMostFriend.exe.sha256 b/public/topmostfriend/dl/v1.0.0/TopMostFriend.exe.sha256 new file mode 100644 index 0000000..dd7c413 --- /dev/null +++ b/public/topmostfriend/dl/v1.0.0/TopMostFriend.exe.sha256 @@ -0,0 +1 @@ +c5e76254a2951676173559fa1a3da82b092759c2dfbed75e00f6228655b1cbb8 \ No newline at end of file diff --git a/public/topmostfriend/dl/v1.0.0/changelog.txt b/public/topmostfriend/dl/v1.0.0/changelog.txt new file mode 100644 index 0000000..ce87d7f --- /dev/null +++ b/public/topmostfriend/dl/v1.0.0/changelog.txt @@ -0,0 +1,3 @@ +v1.0.0 - 2020-01-05 + +[+] Initial Release. diff --git a/public/topmostfriend/dl/v1.0.0/topmostfriend-1.0.0.zip b/public/topmostfriend/dl/v1.0.0/topmostfriend-1.0.0.zip new file mode 100644 index 0000000..bdf332b Binary files /dev/null and b/public/topmostfriend/dl/v1.0.0/topmostfriend-1.0.0.zip differ diff --git a/public/topmostfriend/dl/v1.1.0/TopMostFriend.exe b/public/topmostfriend/dl/v1.1.0/TopMostFriend.exe new file mode 100644 index 0000000..1867dad Binary files /dev/null and b/public/topmostfriend/dl/v1.1.0/TopMostFriend.exe differ diff --git a/public/topmostfriend/dl/v1.1.0/TopMostFriend.exe.sha256 b/public/topmostfriend/dl/v1.1.0/TopMostFriend.exe.sha256 new file mode 100644 index 0000000..ef9533a --- /dev/null +++ b/public/topmostfriend/dl/v1.1.0/TopMostFriend.exe.sha256 @@ -0,0 +1 @@ +e8a9d9d957c855b716952b763011d9eed0ffd1c26f483e17440dc3c2f4791187 \ No newline at end of file diff --git a/public/topmostfriend/dl/v1.1.0/changelog.txt b/public/topmostfriend/dl/v1.1.0/changelog.txt new file mode 100644 index 0000000..7ab46c2 --- /dev/null +++ b/public/topmostfriend/dl/v1.1.0/changelog.txt @@ -0,0 +1,5 @@ +v1.1.0 - 2020-01-06 + +[+] Added ability to register a hotkey to toggle the currently active window between always on top and not. +[+] Added a couple registry values for customisation and hidden list items. +[*] Ensuring that only one instance is running. diff --git a/public/topmostfriend/dl/v1.1.0/topmostfriend-1.1.0.zip b/public/topmostfriend/dl/v1.1.0/topmostfriend-1.1.0.zip new file mode 100644 index 0000000..6929074 Binary files /dev/null and b/public/topmostfriend/dl/v1.1.0/topmostfriend-1.1.0.zip differ diff --git a/public/topmostfriend/dl/v1.2.0/TopMostFriend.exe b/public/topmostfriend/dl/v1.2.0/TopMostFriend.exe new file mode 100644 index 0000000..32896dc Binary files /dev/null and b/public/topmostfriend/dl/v1.2.0/TopMostFriend.exe differ diff --git a/public/topmostfriend/dl/v1.2.0/TopMostFriend.exe.sha256 b/public/topmostfriend/dl/v1.2.0/TopMostFriend.exe.sha256 new file mode 100644 index 0000000..5b030ea --- /dev/null +++ b/public/topmostfriend/dl/v1.2.0/TopMostFriend.exe.sha256 @@ -0,0 +1 @@ +5635e10be9fd1facea623018fc230ab3173edd74a255b40ce82f2b9998ad7b63 \ No newline at end of file diff --git a/public/topmostfriend/dl/v1.2.0/changelog.txt b/public/topmostfriend/dl/v1.2.0/changelog.txt new file mode 100644 index 0000000..c910ed3 --- /dev/null +++ b/public/topmostfriend/dl/v1.2.0/changelog.txt @@ -0,0 +1,7 @@ +v1.2.0 - 2020-01-07 + +[+] Added option to always ask for admin on start. +[+] Added error message when topmost toggle fails, if it fails and the process isn't running as administrator it'll ask to elevate. +[+] Added --reset-admin cli flag to revert always admin status. +[+] Added --hwnd= cli flag which allows for toggling a window's topmost status immediately. Used by the elevation prompt. +[+] Added --stop cli flag to close the program after processing cli flags. diff --git a/public/topmostfriend/dl/v1.2.0/topmostfriend-1.2.0.zip b/public/topmostfriend/dl/v1.2.0/topmostfriend-1.2.0.zip new file mode 100644 index 0000000..9bc2464 Binary files /dev/null and b/public/topmostfriend/dl/v1.2.0/topmostfriend-1.2.0.zip differ diff --git a/public/topmostfriend/dl/v1.3.0/TopMostFriend.exe b/public/topmostfriend/dl/v1.3.0/TopMostFriend.exe new file mode 100644 index 0000000..1c008f7 Binary files /dev/null and b/public/topmostfriend/dl/v1.3.0/TopMostFriend.exe differ diff --git a/public/topmostfriend/dl/v1.3.0/TopMostFriend.exe.sha256 b/public/topmostfriend/dl/v1.3.0/TopMostFriend.exe.sha256 new file mode 100644 index 0000000..7877f98 --- /dev/null +++ b/public/topmostfriend/dl/v1.3.0/TopMostFriend.exe.sha256 @@ -0,0 +1 @@ +e4798d009d24ec412b5d4c1eb3e46764a863529ac4a1b5b3e82da35484f2af83 \ No newline at end of file diff --git a/public/topmostfriend/dl/v1.3.0/changelog.txt b/public/topmostfriend/dl/v1.3.0/changelog.txt new file mode 100644 index 0000000..23bcf69 --- /dev/null +++ b/public/topmostfriend/dl/v1.3.0/changelog.txt @@ -0,0 +1,4 @@ +v1.3.0 - 2020-01-12 + +[+] Added notification balloon on hotkey toggle, disabled by default on Windows 10 and beyond. +[-] Removed useless left click handler. diff --git a/public/topmostfriend/dl/v1.3.0/topmostfriend-1.3.0.zip b/public/topmostfriend/dl/v1.3.0/topmostfriend-1.3.0.zip new file mode 100644 index 0000000..9f2b572 Binary files /dev/null and b/public/topmostfriend/dl/v1.3.0/topmostfriend-1.3.0.zip differ diff --git a/public/topmostfriend/dl/v1.4.0/TopMostFriend.exe b/public/topmostfriend/dl/v1.4.0/TopMostFriend.exe new file mode 100644 index 0000000..6a08aef Binary files /dev/null and b/public/topmostfriend/dl/v1.4.0/TopMostFriend.exe differ diff --git a/public/topmostfriend/dl/v1.4.0/TopMostFriend.exe.sha256 b/public/topmostfriend/dl/v1.4.0/TopMostFriend.exe.sha256 new file mode 100644 index 0000000..a988f8c --- /dev/null +++ b/public/topmostfriend/dl/v1.4.0/TopMostFriend.exe.sha256 @@ -0,0 +1 @@ +be300d3cd83e689cfd7a2eee6a4f906187b24ce13f1257da6202298af444b03d \ No newline at end of file diff --git a/public/topmostfriend/dl/v1.4.0/changelog.txt b/public/topmostfriend/dl/v1.4.0/changelog.txt new file mode 100644 index 0000000..e683900 --- /dev/null +++ b/public/topmostfriend/dl/v1.4.0/changelog.txt @@ -0,0 +1,6 @@ +v1.4.0 - 2020-06-10 + +[+] Added hotkey indicator, if used the notification area icon will temporarily change to the affected window's icon. +[-] Removed hidden ShowExplorerMisc registry switch, explorer windows are now just listed like any other. +[-] Removed static exclusion for windows with the title Program Manager or Start. +[+] Added manual title blacklisting system, titles in the previously mentioned change are added to it by default but can be removed if desired. diff --git a/public/topmostfriend/dl/v1.4.0/topmostfriend-1.4.0.zip b/public/topmostfriend/dl/v1.4.0/topmostfriend-1.4.0.zip new file mode 100644 index 0000000..80adca5 Binary files /dev/null and b/public/topmostfriend/dl/v1.4.0/topmostfriend-1.4.0.zip differ diff --git a/public/topmostfriend/dl/v1.4.1/TopMostFriend.exe b/public/topmostfriend/dl/v1.4.1/TopMostFriend.exe new file mode 100644 index 0000000..42447df Binary files /dev/null and b/public/topmostfriend/dl/v1.4.1/TopMostFriend.exe differ diff --git a/public/topmostfriend/dl/v1.4.1/TopMostFriend.exe.sha256 b/public/topmostfriend/dl/v1.4.1/TopMostFriend.exe.sha256 new file mode 100644 index 0000000..916b24f --- /dev/null +++ b/public/topmostfriend/dl/v1.4.1/TopMostFriend.exe.sha256 @@ -0,0 +1 @@ +bd8c5e1e0592c86811bfeb4b6953bfec93a52bd37e18155ddc2a7ba8d429ab27 \ No newline at end of file diff --git a/public/topmostfriend/dl/v1.4.1/changelog.txt b/public/topmostfriend/dl/v1.4.1/changelog.txt new file mode 100644 index 0000000..68d696d --- /dev/null +++ b/public/topmostfriend/dl/v1.4.1/changelog.txt @@ -0,0 +1,3 @@ +v1.4.1 - 2020-06-10 + +[*] Fixed oversight in initial title blacklist generation on Windows Vista and 7. diff --git a/public/topmostfriend/dl/v1.4.1/topmostfriend-1.4.1.zip b/public/topmostfriend/dl/v1.4.1/topmostfriend-1.4.1.zip new file mode 100644 index 0000000..bc2335a Binary files /dev/null and b/public/topmostfriend/dl/v1.4.1/topmostfriend-1.4.1.zip differ diff --git a/public/topmostfriend/dl/v1.4.2/TopMostFriend.exe b/public/topmostfriend/dl/v1.4.2/TopMostFriend.exe new file mode 100644 index 0000000..0839df0 Binary files /dev/null and b/public/topmostfriend/dl/v1.4.2/TopMostFriend.exe differ diff --git a/public/topmostfriend/dl/v1.4.2/TopMostFriend.exe.sha256 b/public/topmostfriend/dl/v1.4.2/TopMostFriend.exe.sha256 new file mode 100644 index 0000000..a2c6ed0 --- /dev/null +++ b/public/topmostfriend/dl/v1.4.2/TopMostFriend.exe.sha256 @@ -0,0 +1 @@ +31290efe7874a3e9eda78abe5498ec3a99c0022d4ae4c53ada922a6ef4855407 \ No newline at end of file diff --git a/public/topmostfriend/dl/v1.4.2/changelog.txt b/public/topmostfriend/dl/v1.4.2/changelog.txt new file mode 100644 index 0000000..2a47d09 --- /dev/null +++ b/public/topmostfriend/dl/v1.4.2/changelog.txt @@ -0,0 +1,3 @@ +v1.4.2 - 2020-07-10 + +[+] Added ability to bind the Windows key for the hotkey combination. diff --git a/public/topmostfriend/dl/v1.4.2/topmostfriend-1.4.2.zip b/public/topmostfriend/dl/v1.4.2/topmostfriend-1.4.2.zip new file mode 100644 index 0000000..4d3b60c Binary files /dev/null and b/public/topmostfriend/dl/v1.4.2/topmostfriend-1.4.2.zip differ diff --git a/public/topmostfriend/dl/v1.5.0/TopMostFriend.exe b/public/topmostfriend/dl/v1.5.0/TopMostFriend.exe new file mode 100644 index 0000000..1503a0e Binary files /dev/null and b/public/topmostfriend/dl/v1.5.0/TopMostFriend.exe differ diff --git a/public/topmostfriend/dl/v1.5.0/TopMostFriend.exe.sha256 b/public/topmostfriend/dl/v1.5.0/TopMostFriend.exe.sha256 new file mode 100644 index 0000000..ba00a0d --- /dev/null +++ b/public/topmostfriend/dl/v1.5.0/TopMostFriend.exe.sha256 @@ -0,0 +1 @@ +fb997a5d83f89c4f633d124b73a85a71404c8e3a5a514982e1f05ae3a547aa56 \ No newline at end of file diff --git a/public/topmostfriend/dl/v1.5.0/changelog.txt b/public/topmostfriend/dl/v1.5.0/changelog.txt new file mode 100644 index 0000000..daf58d0 --- /dev/null +++ b/public/topmostfriend/dl/v1.5.0/changelog.txt @@ -0,0 +1,5 @@ +v1.5.0 - 2021-02-04 + +[+] Added toggle to disable the window list in the context menu. +[+] Added manual refresh button for the window list. +[*] Greatly improved window list loading speed. diff --git a/public/topmostfriend/dl/v1.5.0/topmostfriend-1.5.0.zip b/public/topmostfriend/dl/v1.5.0/topmostfriend-1.5.0.zip new file mode 100644 index 0000000..df55e04 Binary files /dev/null and b/public/topmostfriend/dl/v1.5.0/topmostfriend-1.5.0.zip differ diff --git a/public/topmostfriend/dl/v1.5.1/TopMostFriend.exe b/public/topmostfriend/dl/v1.5.1/TopMostFriend.exe new file mode 100644 index 0000000..d9c1f13 Binary files /dev/null and b/public/topmostfriend/dl/v1.5.1/TopMostFriend.exe differ diff --git a/public/topmostfriend/dl/v1.5.1/TopMostFriend.exe.sha256 b/public/topmostfriend/dl/v1.5.1/TopMostFriend.exe.sha256 new file mode 100644 index 0000000..670e1a5 --- /dev/null +++ b/public/topmostfriend/dl/v1.5.1/TopMostFriend.exe.sha256 @@ -0,0 +1 @@ +11ccbad5a3f6cebce01152eee24466f75f26185d74b3220249b018c1990e31fe \ No newline at end of file diff --git a/public/topmostfriend/dl/v1.5.1/changelog.txt b/public/topmostfriend/dl/v1.5.1/changelog.txt new file mode 100644 index 0000000..1940e49 --- /dev/null +++ b/public/topmostfriend/dl/v1.5.1/changelog.txt @@ -0,0 +1,3 @@ +v1.5.1 - 2021-02-04 + +[*] Fixed massive oversight. diff --git a/public/topmostfriend/dl/v1.5.1/topmostfriend-1.5.1.zip b/public/topmostfriend/dl/v1.5.1/topmostfriend-1.5.1.zip new file mode 100644 index 0000000..dbadb1d Binary files /dev/null and b/public/topmostfriend/dl/v1.5.1/topmostfriend-1.5.1.zip differ diff --git a/public/topmostfriend/door_in.gif b/public/topmostfriend/door_in.gif new file mode 100644 index 0000000..2fc9074 Binary files /dev/null and b/public/topmostfriend/door_in.gif differ diff --git a/public/topmostfriend/downloads.php b/public/topmostfriend/downloads.php new file mode 100644 index 0000000..5c0fb73 --- /dev/null +++ b/public/topmostfriend/downloads.php @@ -0,0 +1,80 @@ +{$title}" + . "{$indent}

{$description}

" + . "{$indent}

Microsoft Windows XP Service Pack 3 and newer are supported, provided .NET Framework 4.0 is installed.

" + . "{$indent}"; + +foreach($files as $fileName) { + $folderName = dirname($fileName); + $changlogName = $folderName . DIRECTORY_SEPARATOR . 'changelog.txt'; + + $changelog = fopen($changlogName, 'rb'); + if(!$changelog) + continue; + + $versionInfo = fgets($changelog); + fclose($changelog); + if($versionInfo === false) + continue; + + $versionInfo = trim($versionInfo); + if(empty($versionInfo)) + continue; + + $buttonClasses = []; + + if(empty($hadLatest)) { + $hadLatest = true; + $isLatest = true; + $latestText = ' Latest!'; + $buttonClasses[] = 'tmf-button-latest'; + } else { + $isLatest = false; + $latestText = ''; + } + + [$version, $date] = explode(' - ', $versionInfo, 2); + $versionId = $version; + $date = strtotime($date); + + $sourceArchive = $folderName . '/topmostfriend-' . substr($version, 1) . '.zip'; + + $sha256File = $fileName . '.sha256'; + $sha256Hash = is_file($sha256File) ? trim(file_get_contents($sha256File)) : ''; + + $body .= sprintf('%s

%s — %s

', $indent, $versionId, $versionId, $version, date('c', $date), date('Y-m-d', $date), $latestText); + + if(empty($sha256Hash)) + $body .= '

SHA256 hash is missing.

'; + else { + $sha256HashFile = hash_file('sha256', $fileName); + $sha256HashMatches = hash_equals($sha256Hash, $sha256HashFile) ? '' : ' (does not match with actual file)'; + $body .= sprintf('

SHA256: %s%s

', $sha256Hash, $sha256HashMatches); + } + + $body .= $indent . '' + . $indent . '
'; +} + +$indent = substr($indent, 0, -4); +$body .= $indent; + +require_once __DIR__ . '/_inc/out.php'; diff --git a/public/topmostfriend/gradient.gif b/public/topmostfriend/gradient.gif new file mode 100644 index 0000000..08aa351 Binary files /dev/null and b/public/topmostfriend/gradient.gif differ diff --git a/public/topmostfriend/help.gif b/public/topmostfriend/help.gif new file mode 100644 index 0000000..fd55b1e Binary files /dev/null and b/public/topmostfriend/help.gif differ diff --git a/public/topmostfriend/icon.gif b/public/topmostfriend/icon.gif new file mode 100644 index 0000000..9d9fb32 Binary files /dev/null and b/public/topmostfriend/icon.gif differ diff --git a/public/topmostfriend/index.php b/public/topmostfriend/index.php index 26fe2a6..8aa56cc 100644 --- a/public/topmostfriend/index.php +++ b/public/topmostfriend/index.php @@ -1,59 +1,38 @@ -Top Most Friend -Top Most Friend
-Home - -Source -
-

Top Most Friend is the next instalment in the friend family of utilities. This friend runs in your system notification area and allows you to force any visible window of any process to always be on top with a simple right click menu or the press of a hotkey.

-

Download for .NET Framework 4.0 (this is not a permalink, SHA256: )

-
-

Changelog

-

v1.4.2

-

-Added ability to bind the Windows key for the hotkey combination. -

-

v1.4.1

-

-Fixed oversight in initial title blacklist generation on Windows Vista and 7. -

-

v1.4.0

-

-Added hotkey indicator, if used the notification area icon will temporarily change to the affected window's icon.
-Removed hidden ShowExplorerMisc registry switch, explorer windows are now just listed like any other.
-Removed static exclusion for windows with the title Program Manager or Start.
-Added manual title blacklisting system, titles in the previously mentioned change are added to it by default but can be removed if desired. -

-

v1.3.0

-

-Added notification balloon on hotkey toggle, disabled by default on Windows 10 and beyond.
-Removed useless left click handler. -

-

v1.2.0

-

-Added option to always ask for admin on start.
-Added error message when topmost toggle fails, if it fails and the process isn't running as administrator it'll ask to elevate.
-Added --reset-admin cli flag to revert always admin status.
-Added --hwnd= cli flag which allows for toggling a window's topmost status immediately. Used by the elevation prompt.
-Added --stop cli flag to close the program after processing cli flags. -

-

v1.1.0

-

-Added ability to register a hotkey to toggle the currently active window between always on top and not.
-Added a couple registry values for customisation and hidden list items.
-Ensuring that only one instance is running. -

-

v1.0.0

-

Initial Release

- +Home' + . $indent . '

Top Most Friend is the next instalment in the friend family of utilities. This friend runs in your system notification area and allows you to force any visible window of any process to always be on top with a simple right click menu or the press of a hotkey.

'; + +$body .= $indent . '
' + . $indent . ' Get the latest version!' + . $indent . '
'; + +$body .= $indent . '

Tray Area

'; +$body .= $indent . 'Main UI in v1.5.1'; +$body .= $indent . '

Top Most Friend runs in your system tray area. When right clicking on it you\'re presented with a menu that contains all currently open windows as well as a number of actions.

'; +$body .= $indent . '

Clicking any of the windows will toggle its always on top status, Refresh will reload the window list without dismissing the menu, Settings will open the settings menu displayed below, About shows the about window displayed in the screenshot, and Quit closes the program.

'; +$body .= $indent . '
'; + +$body .= $indent . '

Settings

'; +$body .= $indent . 'Settings in v1.5.1'; +$body .= $indent . '

In the settings you can alter program behaviour, set a global hotkey that will toggle the always on top status of whichever window currently has focus and open the title blacklist window.

'; +$body .= $indent . '

Some windows require administrator privileges to have their top most status toggled, normally the program will prompt you if this is needed but you can also choose to always make the program start itself as administrator. This will have no effect on version of Windows before Vista.

'; +$body .= $indent . '

You can also choose to omit the program list from the taskbar menu if you only plan on using the hotkey functionality, this will make the menu open ever so slightly faster.

'; +$body .= $indent . '

The other options are fairly self explanatory, if you\'ve accidentally SHIFT+CLICK\'d a window onto the title blacklist you can just open the submenu and remove it again.

'; +$body .= $indent . '
'; + +$body .= $indent . '

Title Blacklisting

'; +$body .= $indent . 'Title blacklist in v1.5.1'; +$body .= $indent . '

The title blacklist functions as a way to keep the list in the menu clean, it does not affect anything in regards to the hotkey. Depending on your version of Windows, a number of items may be added by default which are either invisible windows or cannot be toggled at all.

'; +$body .= $indent . '

You can add, edit and remove entries using a simple text entry screen, as described in the previous section you can also SHIFT+CLICK things in the program list if enable.

'; +$body .= $indent . '
'; + +$body .= $indent . ''; + +$body .= substr($indent, 0, -4); + +require_once __DIR__ . '/_inc/out.php'; diff --git a/public/topmostfriend/index_old.php b/public/topmostfriend/index_old.php new file mode 100644 index 0000000..9c09e1d --- /dev/null +++ b/public/topmostfriend/index_old.php @@ -0,0 +1,70 @@ + +Top Most Friend +Top Most Friend
+Home - +Source +
+

Top Most Friend is the next instalment in the friend family of utilities. This friend runs in your system notification area and allows you to force any visible window of any process to always be on top with a simple right click menu or the press of a hotkey.

+

Download for .NET Framework 4.0 (this is not a permalink, SHA256: )

+
+

Changelog

+

v1.5.1 — 2021-02-04

+

+[*] Fixed massive oversight. +

+

v1.5.0 — 2021-02-04

+

+[+] Added toggle to disable the window list in the context menu.
+[+] Added manual refresh button for the window list.
+[*] Greatly improved window list loading speed. +

+

v1.4.2 — 2020-07-10

+

+[+] Added ability to bind the Windows key for the hotkey combination. +

+

v1.4.1 — 2020-06-10

+

+[*] Fixed oversight in initial title blacklist generation on Windows Vista and 7. +

+

v1.4.0 — 2020-06-10

+

+[+] Added hotkey indicator, if used the notification area icon will temporarily change to the affected window's icon.
+[-] Removed hidden ShowExplorerMisc registry switch, explorer windows are now just listed like any other.
+[-] Removed static exclusion for windows with the title Program Manager or Start.
+[+] Added manual title blacklisting system, titles in the previously mentioned change are added to it by default but can be removed if desired. +

+

v1.3.0 — 2020-01-12

+

+[+] Added notification balloon on hotkey toggle, disabled by default on Windows 10 and beyond.
+[-] Removed useless left click handler. +

+

v1.2.0 — 2020-01-07

+

+[+] Added option to always ask for admin on start.
+[+] Added error message when topmost toggle fails, if it fails and the process isn't running as administrator it'll ask to elevate.
+[+] Added --reset-admin cli flag to revert always admin status.
+[+] Added --hwnd= cli flag which allows for toggling a window's topmost status immediately. Used by the elevation prompt.
+[+] Added --stop cli flag to close the program after processing cli flags. +

+

v1.1.0 — 2020-01-06

+

+[+] Added ability to register a hotkey to toggle the currently active window between always on top and not.
+[+] Added a couple registry values for customisation and hidden list items.
+[*] Ensuring that only one instance is running. +

+

v1.0.0 — 2020-01-05

+

[+] Initial Release

+ diff --git a/public/topmostfriend/logo.png b/public/topmostfriend/logo.png new file mode 100644 index 0000000..a5b4d5b Binary files /dev/null and b/public/topmostfriend/logo.png differ diff --git a/public/topmostfriend/pattern.jpg b/public/topmostfriend/pattern.jpg new file mode 100644 index 0000000..4f8ec43 Binary files /dev/null and b/public/topmostfriend/pattern.jpg differ diff --git a/public/topmostfriend/simulator.js b/public/topmostfriend/simulator.js new file mode 100644 index 0000000..0881f30 --- /dev/null +++ b/public/topmostfriend/simulator.js @@ -0,0 +1,897 @@ +// An attempt was made to make this entirely function in IE8, I gave up at the polishing stage + +// From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys +if(!Object.keys) { + Object.keys = (function() { + 'use strict'; + var hasOwnProperty = Object.prototype.hasOwnProperty, + hasDontEnumBug = !({ toString: null }).propertyIsEnumerable('toString'), + dontEnums = [ + 'toString', + 'toLocaleString', + 'valueOf', + 'hasOwnProperty', + 'isPrototypeOf', + 'propertyIsEnumerable', + 'constructor' + ], + dontEnumsLength = dontEnums.length; + + return function(obj) { + if (typeof obj !== 'function' && (typeof obj !== 'object' || obj === null)) { + throw new TypeError('Object.keys called on non-object'); + } + + var result = [], prop, i; + + for (prop in obj) { + if (hasOwnProperty.call(obj, prop)) { + result.push(prop); + } + } + + if (hasDontEnumBug) { + for (i = 0; i < dontEnumsLength; i++) { + if (hasOwnProperty.call(obj, dontEnums[i])) { + result.push(dontEnums[i]); + } + } + } + return result; + }; + }()); +} + +var tmfBindEvent = function(subject, name, callback) { + if(document.attachEvent) + return subject.attachEvent('on' + name, callback); + return subject.addEventListener(name, callback); +}; + +var tmfOnReady = function(callback) { + if(document.attachEvent) + document.attachEvent('onreadystatechange', function() { + if(document.readyState === 'complete') + callback(); + }); + else + document.addEventListener('DOMContentLoaded', function() { + callback(); + }); +}; + +var tmfCreateElement = function(elemInfo) { + elemInfo = elemInfo || {}; + var elem = document.createElement(elemInfo.tag || 'div'); + + if(elemInfo.props) { + var propKeys = Object.keys(elemInfo.props); + + for(var i = 0; i < propKeys.length; i++) { + var propKey = propKeys[i]; + + if(elemInfo.props[propKey] === undefined + || elemInfo.props[propKey] === null) + continue; + + switch(typeof elemInfo.props[propKey]) { + case 'function': + tmfBindEvent( + elem, + propKey.substring(0, 2) === 'on' + ? propKey.substring(2).toLowerCase() + : propKey, + elemInfo.props[propKey] + ); + break; + + default: + elem.setAttribute(propKey === 'className' ? 'class' : propKey, elemInfo.props[propKey]); + break; + } + } + } + + if(elemInfo.children) { + var children = elemInfo.children; + if(Object.prototype.toString.call(children) !== '[object Array]') + children = [children]; + + for(var i = 0; i < children.length; i++) { + var child = children[i]; + if(typeof child === 'undefined') + continue; + + switch(typeof child) { + case 'string': + elem.appendChild(document.createTextNode(child)); + break; + + case 'object': + if(child instanceof Element) + elem.appendChild(child); + else if(child.getElement) + elem.appendChild(child.getElement()); + else + elem.appendChild(tmfCreateElement(child)); + break; + + default: + elem.appendChild(document.createTextNode(child.toString())); + break; + } + } + } + + if(elemInfo.created) + elemInfo.created(elem); + + return elem; +}; + +var tmfClientRectangle = function() { + if(typeof window.innerWidth !== 'undefined') + return [window.innerWidth, window.innerHeight]; + if(typeof document.documentElement !== 'undefined' + && typeof document.documentElement.clientWidth !== 'undefined' + && document.documentElement.clientWidth !== 0) + return [document.documentElement.clientWidth, document.documentElement.clientHeight]; + var body = document.getElementsByTagName('body')[0]; + return [body.clientWidth, body.clientHeight]; +}; + +var tmfIs12HourClockValue = null; +var tmfIs12Hour = function() { + if(typeof window.tmfIs12HourClockValue === 'boolean') + return window.tmfIs12HourClockValue; + var d = new Date; + return window.tmfIs12HourClockValue = !!(d.toLocaleTimeString().match(/am|pm/i) || d.toString().match(/am|pm/i)); +}; + +var tmfTimeString = function() { + var date = new Date, + str = '', + stupid = tmfIs12Hour(), + dumb = '', + hours = date.getHours(), + mins = date.getMinutes(); + + if(stupid) { + dumb = hours > 11 ? 'pm' : 'am'; + if(hours === 0) + hours = 12; + } + + str = hours.toString() + ':'; + + if(mins < 10) + str += '0'; + str += mins.toString(); + + if(stupid) + str += ' ' + dumb; + + return str; +}; + +var tmfSetElemText = function(elem, text) { + if(typeof elem.textContent !== 'undefined') + elem.textContent = text; + else if(typeof elem.innerText !== 'undefined') + elem.innerText = text; + else { + elem.innerHTML = ''; + elem.appendChild(document.createTextNode(text)); + } +}; + +var tmfCreateMenuItem = function(name, icon, click) { + var item = tmfCreateElement({ + props: { className: 'tmfs-menu-item' }, + children: [ + { + props: { className: 'tmfs-menu-item-icon' }, + children: { + tag: 'img', + props: { + src: icon, + alt: name, + }, + }, + }, + { + props: { className: 'tmfs-menu-item-text' }, + children: name, + }, + ], + }); + tmfBindEvent(item, 'click', click); + return item; +}; + +var tmfRemoveElement = function(elem) { + if(elem && elem.parentNode) + elem.parentNode.removeChild(elem); +}; + +var tmfGetCentrePosition = function(width, height) { + var rect = tmfClientRectangle(); + rect[0] /= 2; + rect[1] /= 2; + rect[0] -= Math.ceil(width / 2); + rect[1] -= Math.ceil(height / 2); + return rect; +}; +var tmfGetCentrePositionStyle = function(width, height) { + var rect = tmfGetCentrePosition(width, height); + return 'top: ' + rect[1].toString() + 'px; left: ' + rect[0].toString() + 'px;'; +}; + +var tmfShowAbout = function() { + var about = tmfCreateElement({ + props: { + className: 'tmfs-about', + style: tmfGetCentrePositionStyle(445, 120), + }, + children: [ + { + props: { + className: 'tmfs-about-drag', + onmousedown: function() { + tmfSetDragging(about); + }, + }, + }, + { + props: { className: 'tmfs-about-version' }, + children: [ + 'v1.5.1', + { tag: 'br' }, + 'Simulator', + ], + }, + { + tag: 'input', + props: { + className: 'tmfs-about-button tmfs-about-button-donate', + type: 'button', + value: 'Donate', + onClick: function() { + tmfRemoveElement(about); + document.getElementById('_nav_donate').click(); + }, + }, + }, + { + tag: 'input', + props: { + className: 'tmfs-about-button tmfs-about-button-website', + type: 'button', + value: 'Website', + onClick: function() { + tmfRemoveElement(about); + // should this do anything? we're already there lol + }, + }, + }, + { + tag: 'input', + props: { + className: 'tmfs-about-button tmfs-about-button-close', + type: 'button', + value: 'Close', + onClick: function() { + tmfRemoveElement(about); + }, + }, + }, + { + tag: 'a', + props: { + className: 'tmfs-about-credit', + href: '//flash.moe', + target: '_blank', + rel: 'noopener', + }, + }, + { + tag: 'a', + props: { + className: 'tmfs-about-credit tmfs-about-credit-fff', + href: 'http://www.famfamfam.com/lab/icons/silk/', + target: '_blank', + rel: 'noopener', + }, + }, + ], + }); + + document.body.appendChild(about); +}; + +var tmfCtxMenu = null; +var tmfShowCtxMenu = function(xpos, ypos) { + tmfDestroyCtxMenu(); + + var refresh = tmfCreateMenuItem('Refresh', './arrow_refresh.gif', function() { + // can this do anything? + }), settings = tmfCreateMenuItem('Settings', './cog.gif', function() { + tmfDestroyCtxMenu(); + tmfShowSettings(); + }), about = tmfCreateMenuItem('About', './help.gif', function() { + tmfDestroyCtxMenu(); + tmfShowAbout(); + }), quit = tmfCreateMenuItem('Quit', './door_in.gif', function() { + tmfDestroyCtxMenu(); + tmfDestroySysIcon(); + }); + + tmfCtxMenu = tmfCreateElement({ + props: { + className: 'tmfs-menu', + }, + children: [ + refresh, + settings, + about, + quit, + ], + }); + + document.body.appendChild(tmfCtxMenu); + + xpos -= tmfCtxMenu.offsetWidth; + ypos -= tmfCtxMenu.offsetHeight; + + tmfCtxMenu.style.top = ypos.toString() + 'px'; + tmfCtxMenu.style.left = xpos.toString() + 'px'; +}; + +var tmfDestroyCtxMenu = function() { + if(tmfCtxMenu) + tmfRemoveElement(tmfCtxMenu); + tmfCtxMenu = null; +}; + +var tmfSysIcon = null; +var tmfDestroySysIcon = function() { + if(tmfSysIcon) + tmfRemoveElement(tmfSysIcon); + tmfSysIcon = null; +}; + +var tmfDragging = null, tmfDragLastX = 0, tmfDragLastY = 0; +var tmfSetDragging = function(elem) { + tmfDragging = elem; +}; +var tmfStopDragging = function() { + tmfDragging = null; +}; +var tmfDragHandler = function(ev) { + var movX = ev.screenX - tmfDragLastX, + movY = ev.screenY - tmfDragLastY; + tmfDragLastX = ev.screenX; + tmfDragLastY = ev.screenY; + if(tmfDragging === null) + return; + var xpos = tmfDragging.offsetLeft + movX, + ypos = tmfDragging.offsetTop + movY; + tmfDragging.style.left = xpos.toString() + 'px'; + tmfDragging.style.top = ypos.toString() + 'px'; +}; + +var tmfCreateWindow = function(title, className, width, height, closeHandler) { + var frame, body = tmfCreateElement({ + props: { className: 'tmfs-window-body' }, + }); + + if(!closeHandler) + closeHandler = function() { + tmfRemoveElement(frame); + }; + + frame = tmfCreateElement({ + props: { + className: 'tmfs-window ' + className, + style: tmfGetCentrePositionStyle(width, height), + }, + children: [ + { + props: { + className: 'tmfs-window-title', + onmousedown: function() { + tmfSetDragging(frame); + }, + }, + children: [ + { + tag: 'img', + props: { + className: 'tmfs-window-title-icon', + alt: 'ico', + src: './icon.gif', + }, + }, + { + props: { + className: 'tmfs-window-title-close', + onclick: closeHandler, + }, + children: 'X', + }, + { + props: { + className: 'tmfs-window-title-text', + }, + children: title.toString(), + }, + ], + }, + body, + ], + }); + + document.body.appendChild(frame); + + return { + frame: frame, + body: body, + }; +}; + +var tmfCreateFieldset = function(title, className) { + var body = tmfCreateElement({ + props: { + className: 'tmfs-fieldset-body', + } + }); + + var frame = tmfCreateElement({ + tag: 'fieldset', + props: { + className: 'tmfs-fieldset ' + className, + }, + children: [ + { + tag: 'legend', + props: { + className: 'tmfs-fieldset-title', + }, + children: title.toString() + }, + body, + ], + }); + + return { + frame: frame, + body: body, + }; +}; + +var tmfCreateCheckbox = function(className, label, state, enabled, onChange) { + return tmfCreateElement({ + tag: 'label', + props: { + className: 'tmfs-checkbox ' + className, + }, + children: [ + { + tag: 'input', + props: { + type: 'checkbox', + className: 'tmfs-checkbox-input', + checked: state ? true : undefined, + disabled: enabled ? undefined : true, + onchange: function(ev) { onChange(ev.target.checked) }, + }, + }, + { + props: { + className: 'tmfs-checkbox-label', + }, + children: label.toString(), + } + ], + }); +}; + +var tmfSettingsWindow = null; +var tmfCloseSettings = function() { + if(tmfSettingsWindow === null) + return; + tmfRemoveElement(tmfSettingsWindow); + tmfSettingsWindow = null; +}; +var tmfShowSettings = function() { + tmfCloseSettings(); + + var wnd = tmfCreateWindow('Top Most Friend Settings', 'tmfs-settings', 436, 323), + settings = tmfConfig; + tmfSettingsWindow = wnd.frame; + + var hotkeys = tmfCreateFieldset('Hotkeys', 'tmfs-settings-fieldset tmfs-settings-hotkeys'), + flags = tmfCreateFieldset('Flags', 'tmfs-settings-fieldset tmfs-settings-flags'), + blacklist = tmfCreateFieldset('Blacklist', 'tmfs-settings-fieldset tmfs-settings-blacklist'); + + var hotKeyChar = String.fromCharCode((settings.ForegroundHotKey & 0xFFFF0000) >> 16); + + hotkeys.body.appendChild(tmfCreateElement({ + props: { + className: 'tmfs-settings-hotkey-label', + }, + children: 'Toggle always on top status on active window', + })); + hotkeys.body.appendChild(tmfCreateElement({ + tag: 'input', + props: { + id: '_settings_hotkey_key', + type: 'text', + value: hotKeyChar, + className: 'tmfs-settings-hotkey-key', + onkeydown: function(ev) { + var keyCode = (typeof ev.key !== 'undefined') + ? ev.key.toUpperCase().charCodeAt(0) + : ev.keyCode; + settings.ForegroundHotKey &= 0xFFFF; + settings.ForegroundHotKey |= keyCode << 16; + ev.target.value = String.fromCharCode(keyCode); + if(ev.preventDefault) + ev.preventDefault(); + return false; + }, + } + })); + hotkeys.body.appendChild(tmfCreateElement({ + tag: 'input', + props: { + id: '_settings_hotkey_ctrl', + type: 'button', + value: 'CTRL', + className: 'tmfs-settings-hotkey-mod tmfs-settings-hotkey-mod-ctrl' + ((settings.ForegroundHotKey & 0x2) ? ' pressed' : ''), + onclick: function(ev) { + if(settings.ForegroundHotKey & 0x2) { + ev.target.className = ev.target.className.replace(' pressed', ''); + settings.ForegroundHotKey &= ~0x2; + } else { + ev.target.className += ' pressed'; + settings.ForegroundHotKey |= 0x2; + } + }, + } + })); + hotkeys.body.appendChild(tmfCreateElement({ + tag: 'input', + props: { + id: '_settings_hotkey_alt', + type: 'button', + value: 'ALT', + className: 'tmfs-settings-hotkey-mod tmfs-settings-hotkey-mod-alt' + ((settings.ForegroundHotKey & 0x1) ? ' pressed' : ''), + onclick: function(ev) { + if(settings.ForegroundHotKey & 0x1) { + ev.target.className = ev.target.className.replace(' pressed', ''); + settings.ForegroundHotKey &= ~0x1; + } else { + ev.target.className += ' pressed'; + settings.ForegroundHotKey |= 0x1; + } + }, + } + })); + hotkeys.body.appendChild(tmfCreateElement({ + tag: 'input', + props: { + id: '_settings_hotkey_shift', + type: 'button', + value: 'SHIFT', + className: 'tmfs-settings-hotkey-mod tmfs-settings-hotkey-mod-shift' + ((settings.ForegroundHotKey & 0x4) ? ' pressed' : ''), + onclick: function(ev) { + if(settings.ForegroundHotKey & 0x4) { + ev.target.className = ev.target.className.replace(' pressed', ''); + settings.ForegroundHotKey &= ~0x4; + } else { + ev.target.className += ' pressed'; + settings.ForegroundHotKey |= 0x4; + } + }, + } + })); + hotkeys.body.appendChild(tmfCreateElement({ + tag: 'input', + props: { + id: '_settings_hotkey_win', + type: 'button', + value: 'WIN', + className: 'tmfs-settings-hotkey-mod tmfs-settings-hotkey-mod-win' + ((settings.ForegroundHotKey & 0x8) ? ' pressed' : ''), + onclick: function(ev) { + if(settings.ForegroundHotKey & 0x8) { + ev.target.className = ev.target.className.replace(' pressed', ''); + settings.ForegroundHotKey &= ~0x8; + } else { + ev.target.className += ' pressed'; + settings.ForegroundHotKey |= 0x8; + } + }, + } + })); + hotkeys.body.appendChild(tmfCreateElement({ + tag: 'input', + props: { + type: 'button', + value: 'Reset', + className: 'tmfs-settings-hotkey-reset', + onclick: function(ev) { + settings.ForegroundHotKey = 0; + document.getElementById('_settings_hotkey_key').value = ''; + var meow = ['ctrl', 'alt', 'shift', 'win']; + for(var i = 0; i < meow.length; ++i) { + var mewow = document.getElementById('_settings_hotkey_' + meow[i]); + mewow.className = mewow.className.replace(' pressed', ''); + } + }, + } + })); + + flags.body.appendChild(tmfCreateCheckbox('tmfs-settings-checkbox tmfs-settings-checkbox-admin', 'Always run as administrator', settings.RunAsAdministrator, true, function(state) { settings.RunAsAdministrator = state; })); + flags.body.appendChild(tmfCreateCheckbox('tmfs-settings-checkbox tmfs-settings-checkbox-hotkey', 'Show notification when using toggle hotkey', settings.ShowNotificationOnHotKey, true, function(state) { settings.ShowNotificationOnHotKey = state; })); + flags.body.appendChild(tmfCreateCheckbox('tmfs-settings-checkbox tmfs-settings-checkbox-shiftclick', 'SHIFT+CLICK items in the list to add to the title blacklist', settings.ShiftClickToBlacklist, true, function(state) { settings.ShiftClickToBlacklist = state; })); + flags.body.appendChild(tmfCreateCheckbox('tmfs-settings-checkbox tmfs-settings-checkbox-icon', 'Show icon of window affected by hotkey', settings.ShowHotkeyIcon, true, function(state) { settings.ShowHotkeyIcon = state; })); + flags.body.appendChild(tmfCreateCheckbox('tmfs-settings-checkbox tmfs-settings-checkbox-list', 'Show list of open windows in the task bar context menu', settings.ShowWindowList, false, function(state) { settings.ShowWindowList = state; })); + + blacklist.body.appendChild(tmfCreateElement({ + tag: 'input', + props: { + type: 'button', + value: 'Manage...', + className: 'tmfs-settings-button tmfs-settings-blacklist-button', + onclick: function() { + tmfShowBlacklist(); + }, + }, + })); + + wnd.body.appendChild(hotkeys.frame); + wnd.body.appendChild(flags.frame); + wnd.body.appendChild(blacklist.frame); + + wnd.body.appendChild(tmfCreateElement({ + tag: 'input', + props: { + type: 'button', + className: 'tmfs-settings-button tmfs-settings-button-ok', + value: 'OK', + onclick: function() { + tmfConfig = settings; + tmfCloseSettings(); + }, + } + })); + wnd.body.appendChild(tmfCreateElement({ + tag: 'input', + props: { + type: 'button', + className: 'tmfs-settings-button tmfs-settings-button-cancel', + value: 'Cancel', + onclick: function() { + tmfCloseSettings(); + }, + } + })); + wnd.body.appendChild(tmfCreateElement({ + tag: 'input', + props: { + type: 'button', + className: 'tmfs-settings-button tmfs-settings-button-apply', + value: 'Apply', + onclick: function() { + tmfConfig = settings; + }, + } + })); + + //tmfShowBlacklist(); +}; + +var tmfBlacklistWindow = null; +var tmfCloseBlacklist = function() { + if(tmfBlacklistWindow === null) + return; + tmfRemoveElement(tmfBlacklistWindow); + tmfBlacklistWindow = null; +}; +var tmfShowBlacklist = function() { + tmfCloseBlacklist(); + + var wnd = tmfCreateWindow('Title Blacklist', 'tmfs-blacklist', 418, 230), + blacklist = tmfConfig.TitleBlacklist, + listView = tmfCreateElement({ + tag: 'select', + props: { + className: 'tmfs-blacklist-list', + size: 15, + }, + }); + tmfBlacklistWindow = wnd.frame; + wnd.body.appendChild(listView); + + var refreshList = function() { + listView.innerHTML = ''; + for(var i = 0; i < blacklist.length; ++i) + listView.appendChild(tmfCreateElement({ + tag: 'option', + children: blacklist[i].toString(), + })); + }; + + refreshList(); + + wnd.body.appendChild(tmfCreateElement({ + tag: 'input', + props: { + type: 'button', + className: 'tmfs-blacklist-button tmfs-blacklist-button-add', + value: 'Add', + onclick: function() { + var title = prompt('Add new entry...'); + if(title && blacklist.indexOf(title) < 0) + blacklist.push(title); + refreshList(); + }, + }, + })); + wnd.body.appendChild(tmfCreateElement({ + tag: 'input', + props: { + type: 'button', + className: 'tmfs-blacklist-button tmfs-blacklist-button-edit', + value: 'Edit', + onclick: function() { + var selected = blacklist.indexOf(listView.value); + if(selected < 0) + return; + var title = prompt('Editing ' + listView.value + '...'); + if(title && blacklist.indexOf(title) < 0) { + blacklist.splice(selected, 1); + blacklist.push(title); + } + refreshList(); + }, + }, + })); + wnd.body.appendChild(tmfCreateElement({ + tag: 'input', + props: { + type: 'button', + className: 'tmfs-blacklist-button tmfs-blacklist-button-remove', + value: 'Remove', + onclick: function() { + var selected = blacklist.indexOf(listView.value); + if(selected < 0) + return; + blacklist.splice(selected, 1); + refreshList(); + }, + }, + })); + + wnd.body.appendChild(tmfCreateElement({ + tag: 'input', + props: { + type: 'button', + className: 'tmfs-blacklist-button tmfs-blacklist-button-done', + value: 'Done', + onclick: function() { + tmfConfig.TitleBlacklist = blacklist; + tmfCloseBlacklist(); + }, + }, + })); + wnd.body.appendChild(tmfCreateElement({ + tag: 'input', + props: { + type: 'button', + className: 'tmfs-blacklist-button tmfs-blacklist-button-cancel', + value: 'Cancel', + onclick: function() { + tmfCloseBlacklist(); + }, + }, + })); +}; + +var tmfConfig = { + ForegroundHotKey: 0, + RunAsAdministrator: false, + ShowNotificationOnHotKey: true, + ShiftClickToBlacklist: true, + ShowHotkeyIcon: true, + ShowWindowList: false, + TitleBlacklist: [ + 'Start', + 'Program Manager', + 'Windows Shell Experience Host', + ], +}; + +tmfOnReady(function(ev) { + var rect = tmfClientRectangle(); + if(rect[1] > rect[0]) // height is larger than width, we're presemably running on a phone + return; + + var clock = tmfCreateElement({ + props: { className: 'tmfs-clock' }, + children: tmfTimeString(), + }); + + tmfSysIcon = tmfCreateElement({ + tag: 'img', + props: { + className: 'tmfs-icon', + alt: 'TopMostFriend', + title: 'Top Most Application Manager', + src: './icon.gif', + }, + }); + + var taskbar = tmfCreateElement({ + props: { className: 'tmfs' }, + children: { + props: { className: 'tmfs-inner' }, + children: [ + { + props: { className: 'tmfs-left' }, + children: { + props: { className: 'tmfs-start' }, + children: [ + { + tag: 'img', + props: { + alt: '', + src: './start.gif', + }, + }, + 'Start', + ], + }, + }, + { + props: { className: 'tmfs-right' }, + children: { + props: { className: 'tmfs-systray' }, + children: [ + tmfSysIcon, + clock, + ], + }, + }, + { props: { className: 'tmf-clear' } }, + ] + }, + }); + + document.getElementById('_tmf').style.paddingBottom = '30px'; + document.body.appendChild(taskbar); + + /*tmfBindEvent(tmfSysIcon, 'click', function(ev) { + if(ev.shiftKey) + return true; + tmfShowCtxMenu(ev.clientX, ev.clientY); + if(ev.preventDefault) + ev.preventDefault(); + return false; + });*/ + tmfBindEvent(tmfSysIcon, 'contextmenu', function(ev) { + if(ev.shiftKey) + return true; + tmfShowCtxMenu(ev.clientX, ev.clientY); + if(ev.preventDefault) + ev.preventDefault(); + return false; + }); + tmfBindEvent(document, 'mousemove', tmfDragHandler); + tmfBindEvent(document, 'mouseup', tmfStopDragging); + + setInterval(function() { + tmfSetElemText(clock, tmfTimeString()); + }, 1000); +}); diff --git a/public/topmostfriend/ss-main.jpg b/public/topmostfriend/ss-main.jpg new file mode 100644 index 0000000..9b76907 Binary files /dev/null and b/public/topmostfriend/ss-main.jpg differ diff --git a/public/topmostfriend/ss-settings-blacklist.jpg b/public/topmostfriend/ss-settings-blacklist.jpg new file mode 100644 index 0000000..13d0ff6 Binary files /dev/null and b/public/topmostfriend/ss-settings-blacklist.jpg differ diff --git a/public/topmostfriend/ss-settings.jpg b/public/topmostfriend/ss-settings.jpg new file mode 100644 index 0000000..a1f92d0 Binary files /dev/null and b/public/topmostfriend/ss-settings.jpg differ diff --git a/public/topmostfriend/start.gif b/public/topmostfriend/start.gif new file mode 100644 index 0000000..f5dd09c Binary files /dev/null and b/public/topmostfriend/start.gif differ diff --git a/public/topmostfriend/style.css b/public/topmostfriend/style.css new file mode 100644 index 0000000..69bbccf --- /dev/null +++ b/public/topmostfriend/style.css @@ -0,0 +1,483 @@ +* { + margin: 0; + padding: 0; + box-sizing: border-box; + position: relative; + outline-style: none !important; +} + +html, +body { + width: 100%; + height: 100%; +} + +body { + background-color: #111; + color: #fff; + font: 12px/20px Tahoma, Geneva, 'Dejavu Sans', Arial, Helvetica, sans-serif; + padding-top: 2px; +} + +.tmf { + max-width: 1000px; + margin: 0 auto; +} + +.tmf-head { + background: #222; + padding: 2px; +} +.tmf-head-nav { + font-size: 1.4em; +} +.tmf-head-nav li { + list-style: none; + float: left; +} +.tmf-head-nav a:hover, +.tmf-head-nav a:focus, +.tmf-head-nav li.current a { + background-image: url('pattern.jpg'); + background-attachment: fixed; +} +.tmf-head-nav a { + color: #fff; + text-decoration: none; + padding: 8px 10px; + display: inline-block; +} +.tmf-head-logo { + clear: both; + background-image: url('pattern.jpg'); + background-attachment: fixed; + padding: 20px; + padding-top: 26px; +} +.tmf-head-logo h1 { + font-size: 0; + background-image: url('logo.png'); + width: 269px; + height: 43px; +} + +.tmf-clear { + clear: both; +} + +.tmf-foot { + font-size: .9em; + text-align: center; + color: #555; + margin: 5px; +} +.tmf-foot a { + color: #555 !important; + text-decoration: none !important; +} +.tmf-foot a:hover, +.tmf-foot a:focus { + text-decoration: underline !important; +} + +.tmf-body { + padding: 2px; + background-color: #222; + margin: 2px 0; +} + +.tmf h2 { + line-height: 1.5em; + border-bottom: 1px solid #444; +} + +.tmf--home h3, +.tmf--changelog h3, +.tmf--downloads h3 { + margin-top: .5em; + border-bottom: 1px solid #333; +} +.tmf--changelog a, +.tmf--downloads a { + color: #fff; + text-decoration: none; +} + +.tmf--downloads h3 { + margin-top: 1em; +} + +.tmf-buttons { + list-style: none; +} + +.tmf-button { + float: left; + margin: 2px 1px; +} + +.tmf-button a { + padding: 10px; + display: inline-block; + background-color: #555; + font-size: 1.2em; +} +.tmf-button-major a { + padding: 10px 60px; + background-color: #595; +} + +.tmf-button-latest a { + padding: 20px 30px; + font-size: 1.3em; +} +.tmf-button-latest .tmf-button-major a { + padding: 20px 60px; +} + +.tmf-external { + color: #77f !important; + text-decoration: none !important; +} +.tmf-external:hover, +.tmf-external:focus { + text-decoration: underline !important; +} +.tmf-external:active { + color: #f77 !important; +} + +.tmf--home img { + float: right; + margin: 2px; + max-width: 100%; +} + +.tmf--home p { + margin: .5em 0; +} + +@media(max-width: 700px) { + .tmf--home img { + float: none !important; + margin: 2px auto; + display: block; + } +} + +.tmf-godownload { + text-align: center; +} +.tmf-godownload a { + display: inline-block; + padding: 20px 60px; + background-color: #595; + font-size: 1.3em; + color: #fff; + text-decoration: none; +} + +.tmfs { + position: fixed; + bottom: 0; + left: 0; + right: 0; + background: #d4d0c8; + height: 30px; + color: #000; +} +.tmfs-inner { + margin-top: 1px; + border-top: 1px solid #fff; +} +.tmfs-left { + float: left; +} +.tmfs-right { + float: right; +} +.tmfs-systray { + border: 1px inset #fff; + height: 24px; + margin: 2px; + padding: 0 4px; +} +.tmfs-systray * { + float: left; +} +.tmfs-systray img { + margin-top: 2px; + margin-right: 4px; +} +.tmfs-clock { + margin-left: 2px; +} +.tmfs-start { + border: 2px outset #bbb; + height: 24px; + margin: 2px; + padding: 0 4px; + font-weight: 700; +} +.tmfs-start img { + vertical-align: bottom; + margin-right: 3px; +} +.tmfs-menu { + position: fixed; + z-index: 1000; + background: #f9f8f7; + border: 1px solid #666; + color: #000; + box-shadow: 1px 1px 2px #000; +} +.tmfs-menu-item { + height: 24px; + min-width: 120px; +} +.tmfs-menu-item-icon { + background-image: url('gradient.gif'); + width: 24px; + height: 24px; + float: left; +} +.tmfs-menu-item-icon img { + margin: 4px; + vertical-align: middle; +} +.tmfs-menu-item-text { + float: left; + padding: 0 10px; + line-height: 22px; +} +.tmfs-about { + position: fixed; + background-image: url('about.jpg'); + width: 445px; + height: 120px; + overflow: hidden; +} +.tmfs-about-version { + position: absolute; + top: 79px; + left: 128px; + line-height: 16px; +} +.tmfs-about-button { + position: absolute; + width: 70px; + height: 22px; + top: 88px; +} +.tmfs-about-button-close { + left: 363px; +} +.tmfs-about-button-website { + left: 286px; +} +.tmfs-about-button-donate { + left: 209px; +} +.tmfs-about-credit { + position: absolute; + width: 300px; + height: 15px; + display: block; + top: 46px; + left: 133px; +} +.tmfs-about-credit-fff { + top: 64px; +} +.tmfs-about-drag { + position: absolute; + width: 100%; + height: 100%; +} + +.tmfs-window { + position: fixed; + width: 400px; + height: 400px; + overflow: hidden; + margin: 2px; + top: 0; + left: 0; + background-color: #d4d0c8; + padding: 1px; + border: 2px outset #ccc; +} +.tmfs-window-title { + background-image: linear-gradient(90deg, #000080, #1084d0); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#000080', endColorstr='#1084d0', GradientType=1); + height: 18px; +} +.tmfs-window-title-icon { + float: left; + vertical-align: middle; + width: 16px; + height: 16px; + margin: 0 2px; + z-index: 200; +} +.tmfs-window-title-text { + font-weight: 700; + font-size: .9em; + line-height: 17px; + z-index: 100; +} +.tmfs-window-title-close { + float: right; + width: 16px; + height: 14px; + border: 2px outset #ccc; + font-weight: 700; + font-size: .9em; + background-color: #d4d0c8; + z-index: 200; + line-height: 9px; + text-align: center; + color: #000; + margin: 2px; + cursor: pointer; +} +.tmfs-window-title-close:active { + border-style: inset; +} + +.tmfs-blacklist { + width: 418px; + height: 230px; +} +.tmfs-blacklist-list { + font-size: .9em; + width: 318px; + height: 192px; + position: absolute; + top: 7px; + left: 88px; +} +.tmfs-blacklist-list option { + padding: 0 2px; +} +.tmfs-blacklist-button { + position: absolute; + width: 75px; + height: 23px; + left: 6px; +} +.tmfs-blacklist-button-add { + top: 7px; +} +.tmfs-blacklist-button-edit { + top: 36px; +} +.tmfs-blacklist-button-remove { + top: 65px; +} +.tmfs-blacklist-button-done { + top: 146px; +} +.tmfs-blacklist-button-cancel { + top: 175px; +} + +.tmfs-fieldset-title { + color: #000; + margin: 0 5px; +} + +.tmfs-checkbox { + color: #000; + display: block; +} +.tmfs-checkbox-label { + display: inline-block; + cursor: pointer; +} + +.tmfs-settings { + width: 436px; + height: 323px; +} +.tmfs-settings-button { + position: absolute; + width: 75px; + height: 23px; + top: 269px; +} +.tmfs-settings-button-ok { + left: 187px; +} +.tmfs-settings-button-cancel { + left: 268px; +} +.tmfs-settings-button-apply { + left: 349px; +} +.tmfs-settings-fieldset { + position: absolute; + width: 418px; + left: 8px; +} +.tmfs-settings-hotkeys { + top: 6px; + height: 70px; +} +.tmfs-settings-flags { + top: 76px; + height: 130px; +} +.tmfs-settings-blacklist { + top: 207px; + height: 55px; +} +.tmfs-settings-blacklist-button { + left: 8px; + top: 2px; + width: 120px; +} +.tmfs-settings-checkbox .tmfs-checkbox-input { + margin: 0 7px; +} +.tmfs-settings-hotkey-label { + color: #000; + position: absolute; + top: 0; + left: 7px; +} +.tmfs-settings-hotkey-key { + width: 100px; + height: 20px; + position: absolute; + left: 7px; + top: 20px; +} +.tmfs-settings-hotkey-mod { + width: 50px; + height: 23px; + position: absolute; + top: 19px; +} +.tmfs-settings-hotkey-mod.pressed { + border: 1px solid #808080; +} +.tmfs-settings-hotkey-mod-ctrl { + left: 115px; +} +.tmfs-settings-hotkey-mod-alt { + left: 165px; +} +.tmfs-settings-hotkey-mod-shift { + left: 215px; +} +.tmfs-settings-hotkey-mod-win { + left: 265px; +} +.tmfs-settings-hotkey-reset { + width: 75px; + height: 23px; + position: absolute; + top: 19px; + left: 328px; +}