Indent code with spaces instead of tabs

This commit is contained in:
foxster-mp4
2023-05-22 10:35:56 -07:00
parent adbc642cb9
commit 0d8e89dd2f
17 changed files with 923 additions and 923 deletions

198
app.html
View File

@@ -1,106 +1,106 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="css/shared.css"> <link rel="stylesheet" href="css/shared.css">
<link rel="stylesheet" href="css/uibanner.css"> <link rel="stylesheet" href="css/uibanner.css">
<link rel="stylesheet" href="css/app.css"> <link rel="stylesheet" href="css/app.css">
</head> </head>
<body class="loading"> <body class="loading">
<div id="loading"> <div id="loading">
<img src="img/loading.gif" alt="loading"> <img src="img/loading.gif" alt="loading">
<p>Loading</p> <p>Loading</p>
</div> </div>
<div id="main"> <div id="main">
<div id="top"> <div id="top">
<!-- Navigation bar --> <!-- Navigation bar -->
<div id="nav-bar"> <div id="nav-bar">
<button id="back" type="button"> <button id="back" type="button">
<i class="bi bi-chevron-left"></i> <i class="bi bi-chevron-left"></i>
Back Back
</button> </button>
<div id="title" class="hidden"> <div id="title" class="hidden">
<img src="img/generic_app.jpeg" alt="generic-app-icon"> <img src="img/generic_app.jpeg" alt="generic-app-icon">
<p>AltSource</p> <p>AltSource</p>
</div> </div>
<a href="https://example.com" class="install hidden"> <a href="https://example.com" class="install hidden">
<button class="uibutton">Free</button> <button class="uibutton">Free</button>
</a> </a>
</div> </div>
</div> </div>
<!-- Content --> <!-- Content -->
<div class="item"> <div class="item">
<div class="app-header"> <div class="app-header">
<div class="content"> <div class="content">
<img src="img/generic_app.jpeg" alt="generic-app-icon"> <img src="img/generic_app.jpeg" alt="generic-app-icon">
<div class="right"> <div class="right">
<div class="text"> <div class="text">
<p class="title">AltSource</p> <p class="title">AltSource</p>
<p class="subtitle">therealFoxster</p> <p class="subtitle">therealFoxster</p>
</div> </div>
<div class="ipa"> <div class="ipa">
<a href="https://example.com" class="install"> <a href="https://example.com" class="install">
<button class="uibutton">Free</button> <button class="uibutton">Free</button>
</a> </a>
<a href="http://example.com" id="download"> <a href="http://example.com" id="download">
Download IPA Download IPA
</a> </a>
</div> </div>
</div> </div>
</div> </div>
<div class="background"></div> <div class="background"></div>
</div> </div>
</div> </div>
<div id="preview" class="section"> <div id="preview" class="section">
<p id="subtitle">The quick brown fox jumps over the lazy dog.</p> <p id="subtitle">The quick brown fox jumps over the lazy dog.</p>
<div class="header"> <div class="header">
<h2>Preview</h2> <h2>Preview</h2>
</div> </div>
<div id="screenshots"></div> <div id="screenshots"></div>
<p id="description"> <p id="description">
The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog.
The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog.
The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog.
The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog.
The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog.
The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog.
</p> </p>
</div> </div>
<div id="whats-new" class="section"> <div id="whats-new" class="section">
<div class="header"> <div class="header">
<h2>What's New</h2> <h2>What's New</h2>
<p id="version-date">Apr 10, 2023</p> <p id="version-date">Apr 10, 2023</p>
</div> </div>
<div class="header"> <div class="header">
<p id="version">Version 2.0</p> <p id="version">Version 2.0</p>
<p id="version-size">0 KB</p> <p id="version-size">0 KB</p>
</div> </div>
<p id="version-description"> <p id="version-description">
The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog.
The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog.
The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog.
The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog.
The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog.
The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog.
</p> </p>
</div> </div>
<div id="permissions" class="section"> <div id="permissions" class="section">
<div class="header"> <div class="header">
<h2>Permissions</h2> <h2>Permissions</h2>
</div> </div>
<div class="permission"> <div class="permission">
<i class="bi-person-fill-check"></i> <i class="bi-person-fill-check"></i>
<div class="text"> <div class="text">
<p class="title">None</p> <p class="title">None</p>
<p class="description">The developer has not specified any permission required by this app.</p> <p class="description">The developer has not specified any permission required by this app.</p>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<script src="js/shared.js"></script> <script src="js/shared.js"></script>
<script src="js/app.js"></script> <script src="js/app.js"></script>
<script src="js/main.js"></script> <script src="js/main.js"></script>
</body> </body>
</html> </html>

View File

@@ -1,25 +1,25 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="css/shared.css"> <link rel="stylesheet" href="css/shared.css">
<link rel="stylesheet" href="css/uibanner.css"> <link rel="stylesheet" href="css/uibanner.css">
<link rel="stylesheet" href="css/apps.css"> <link rel="stylesheet" href="css/apps.css">
</head> </head>
<body class="loading"> <body class="loading">
<div id="loading"> <div id="loading">
<img src="img/loading.gif" alt="loading"> <img src="img/loading.gif" alt="loading">
<p>Loading</p> <p>Loading</p>
</div> </div>
<!-- Add to AltStore banner & navigation bar --> <!-- Add to AltStore banner & navigation bar -->
<div id="top"></div> <div id="top"></div>
<div id="main"> <div id="main">
<div id="apps"></div> <div id="apps"></div>
</div> </div>
<script src="js/shared.js"></script> <script src="js/shared.js"></script>
<script src="js/apps.js"></script> <script src="js/apps.js"></script>
<script src="js/main.js"></script> <script src="js/main.js"></script>
</body> </body>
</html> </html>

View File

@@ -1,154 +1,154 @@
a { a {
color: var(--app-tint-color) color: var(--app-tint-color)
} }
/* Main */ /* Main */
#main { #main {
padding: unset; padding: unset;
overflow: hidden; overflow: hidden;
} }
#main .item { #main .item {
margin-top: 30%; margin-top: 30%;
margin-bottom: 0; margin-bottom: 0;
padding: 1em; padding: 1em;
} }
#nav-bar #title, #nav-bar #title,
#nav-bar .install { #nav-bar .install {
transition: opacity 0.25s ease-in-out; transition: opacity 0.25s ease-in-out;
} }
/* IPA install & download */ /* IPA install & download */
.ipa { .ipa {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
} }
.ipa #download { .ipa #download {
position: absolute; position: absolute;
margin-top: 36px; /* 32px button height + 4px gap */ margin-top: 36px; /* 32px button height + 4px gap */
font-size: 0.65em; font-size: 0.65em;
font-weight: 450; font-weight: 450;
} }
/* Preview */ /* Preview */
#preview { #preview {
position: relative; position: relative;
} }
#preview #subtitle { #preview #subtitle {
text-align: center; text-align: center;
font-size: 0.9em; font-size: 0.9em;
margin: 0 1em; margin: 0 1em;
} }
#preview .header { #preview .header {
margin: 1em 0; margin: 1em 0;
} }
#preview #screenshots { #preview #screenshots {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
overflow: scroll; overflow: scroll;
padding-right: 1em; padding-right: 1em;
} }
#preview #screenshots>img { #preview #screenshots>img {
max-width: 70%; max-width: 70%;
margin-left: 1em; margin-left: 1em;
border-radius: 0.25em; border-radius: 0.25em;
} }
#preview #description { #preview #description {
margin: 1em; margin: 1em;
-webkit-line-clamp: 5; -webkit-line-clamp: 5;
line-clamp: 5; line-clamp: 5;
display: -webkit-box; display: -webkit-box;
-webkit-box-orient: vertical; -webkit-box-orient: vertical;
overflow: hidden; overflow: hidden;
position: relative; position: relative;
word-wrap: break-word word-wrap: break-word
} }
#more button { #more button {
min-width: 0 !important; min-width: 0 !important;
margin-left: 2px !important; margin-left: 2px !important;
padding: 0; padding: 0;
font-size: 15px; font-size: 15px;
font-weight: 500; font-weight: 500;
text-transform: none; text-transform: none;
border-radius: 4px; border-radius: 4px;
border: none; border: none;
background: unset; background: unset;
color: var(--accent-color); color: var(--accent-color);
cursor: pointer; cursor: pointer;
position: absolute; position: absolute;
bottom: 0; bottom: 0;
right: 0; right: 0;
padding-left: 36px; padding-left: 36px;
background: linear-gradient(to right, transparent, var(--color-bg) 35%); background: linear-gradient(to right, transparent, var(--color-bg) 35%);
} }
/* What's new */ /* What's new */
#whats-new, #whats-new,
#permissions { #permissions {
padding: 1em; padding: 1em;
} }
#whats-new .header, #whats-new .header,
#permissions .header { #permissions .header {
margin: 0.35em 0; margin: 0.35em 0;
padding: 0; padding: 0;
} }
#whats-new .header>p:first-of-type { #whats-new .header>p:first-of-type {
opacity: 0.5; opacity: 0.5;
} }
#whats-new .header>p { #whats-new .header>p {
opacity: 0.35; opacity: 0.35;
} }
#whats-new #version-date { #whats-new #version-date {
text-align: right; text-align: right;
} }
#whats-new #version-description { #whats-new #version-description {
-webkit-line-clamp: 3; -webkit-line-clamp: 3;
line-clamp: 3; line-clamp: 3;
display: -webkit-box; display: -webkit-box;
-webkit-box-orient: vertical; -webkit-box-orient: vertical;
overflow: hidden; overflow: hidden;
position: relative; position: relative;
word-wrap: break-word word-wrap: break-word
} }
/* Permissions */ /* Permissions */
#permissions .permission { #permissions .permission {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
align-items: center; align-items: center;
gap: 0.75em; gap: 0.75em;
margin: 0.5em 0; margin: 0.5em 0;
} }
#permissions .permission i { #permissions .permission i {
font-size: 1.55em; font-size: 1.55em;
color: var(--app-tint-color); color: var(--app-tint-color);
} }
#permissions .permission .title { #permissions .permission .title {
font-weight: 550; font-weight: 550;
} }
#permissions .permission .description { #permissions .permission .description {
font-size: 0.9em; font-size: 0.9em;
opacity: 0.5; opacity: 0.5;
} }

View File

@@ -1,27 +1,27 @@
#main { #main {
padding-top: 7rem; padding-top: 7rem;
} }
#apps .app-container { #apps .app-container {
margin: 1em 1rem 3.25em 1rem; margin: 1em 1rem 3.25em 1rem;
} }
#apps .app-container:last-of-type { #apps .app-container:last-of-type {
margin-bottom: 1em; margin-bottom: 1em;
} }
.screenshots { .screenshots {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
justify-content: space-between; justify-content: space-between;
margin-top: 1em; margin-top: 1em;
} }
.screenshots:last-of-type { .screenshots:last-of-type {
margin-bottom: 1em; margin-bottom: 1em;
} }
.screenshot { .screenshot {
max-width: 48%; max-width: 48%;
border-radius: 4px; border-radius: 4px;
} }

View File

@@ -1,19 +1,19 @@
#main { #main {
padding-top: 8rem; padding-top: 8rem;
} }
#news { #news {
padding: 0 1rem; padding: 0 1rem;
} }
.news-item-wrapper { .news-item-wrapper {
margin-bottom: 3em; margin-bottom: 3em;
} }
.news-item-wrapper:last-of-type { .news-item-wrapper:last-of-type {
margin-bottom: 1em; margin-bottom: 1em;
} }
.news-item-wrapper .item { .news-item-wrapper .item {
margin-bottom: 1rem !important; margin-bottom: 1rem !important;
} }

View File

@@ -1,52 +1,52 @@
#main { #main {
padding-top: 2rem; padding-top: 2rem;
} }
#main #title { #main #title {
margin-bottom: 0.35rem; margin-bottom: 0.35rem;
padding: 0 1rem; padding: 0 1rem;
} }
#main input { #main input {
width: 95%; width: 95%;
font-size: 1em; font-size: 1em;
padding: 0.5rem 0.8rem; padding: 0.5rem 0.8rem;
margin-bottom: 1rem; margin-bottom: 1rem;
border: none; border: none;
border-radius: 10px; border-radius: 10px;
background-color: rgba(0, 0, 0, 0.07); background-color: rgba(0, 0, 0, 0.07);
} }
.suggestion { .suggestion {
padding: 1rem 1rem 1rem 0; padding: 1rem 1rem 1rem 0;
margin-left: 1rem; margin-left: 1rem;
font-size: 1.1rem; font-size: 1.1rem;
border-bottom: 0.1px solid var(--color-separator); border-bottom: 0.1px solid var(--color-separator);
} }
.suggestion .bi { .suggestion .bi {
margin-right: 4px; margin-right: 4px;
} }
@media (hover:hover) { @media (hover:hover) {
.suggestion:hover { .suggestion:hover {
opacity: 0.75; opacity: 0.75;
} }
} }
@media (prefers-color-scheme: dark) { @media (prefers-color-scheme: dark) {
#main input { #main input {
background-color: rgba(255, 255, 255, 0.07); background-color: rgba(255, 255, 255, 0.07);
color: white; color: white;
} }
.suggestion { .suggestion {
border-bottom: 0.1px solid var(--color-separator-dark) !important; border-bottom: 0.1px solid var(--color-separator-dark) !important;
} }
} }
#main .textfield { #main .textfield {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
padding: 0 1rem; padding: 0 1rem;
} }

View File

@@ -1,397 +1,397 @@
@import url("https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.4/font/bootstrap-icons.css"); @import url("https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.4/font/bootstrap-icons.css");
:root { :root {
--accent-color: #018084; --accent-color: #018084;
--app-tint-color: #018084; --app-tint-color: #018084;
--color-bg: rgba(255, 255, 255, 255); --color-bg: rgba(255, 255, 255, 255);
--color-separator: rgba(0, 0, 0, 0.15); --color-separator: rgba(0, 0, 0, 0.15);
--color-primary: rgba(0, 122, 254, 255); --color-primary: rgba(0, 122, 254, 255);
--color-transparent: rgba(255, 255, 255, 0.75); --color-transparent: rgba(255, 255, 255, 0.75);
--color-bg-dark: rgb(26, 25, 27); --color-bg-dark: rgb(26, 25, 27);
--color-separator-dark: rgba(255, 255, 255, 0.15); --color-separator-dark: rgba(255, 255, 255, 0.15);
--color-primary-dark: rgba(11, 132, 254, 255); --color-primary-dark: rgba(11, 132, 254, 255);
--color-transparent-dark: rgba(26, 25, 27, 0.25); --color-transparent-dark: rgba(26, 25, 27, 0.25);
} }
* { * {
font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
margin: 0; margin: 0;
} }
/* Dark appearance */ /* Dark appearance */
@media (prefers-color-scheme: dark) { @media (prefers-color-scheme: dark) {
body, body,
.uibanner, .uibanner,
#loading { #loading {
background-color: var(--color-bg-dark) !important; background-color: var(--color-bg-dark) !important;
} }
p, p,
h1, h1,
h2 { h2 {
color: white; color: white;
} }
#nav-bar { #nav-bar {
background-color: var(--color-transparent-dark) !important; background-color: var(--color-transparent-dark) !important;
} }
.uibanner, .uibanner,
#nav-bar { #nav-bar {
border-color: var(--color-separator-dark) !important; border-color: var(--color-separator-dark) !important;
} }
.app-header .background { .app-header .background {
opacity: 0.35 !important; opacity: 0.35 !important;
} }
#more button { #more button {
background: linear-gradient(to right, transparent, var(--color-bg-dark) 35%) !important; background: linear-gradient(to right, transparent, var(--color-bg-dark) 35%) !important;
} }
} }
body.loading { body.loading {
overflow: hidden; overflow: hidden;
} }
#loading { #loading {
position: fixed; position: fixed;
left: 0; left: 0;
right: 0; right: 0;
height: 100vh; height: 100vh;
margin: 0 auto; margin: 0 auto;
z-index: 4; z-index: 4;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
gap: 4px; gap: 4px;
background: var(--color-bg); background: var(--color-bg);
} }
#loading img { #loading img {
width: 24px; width: 24px;
opacity: 0.5; opacity: 0.5;
} }
#loading p { #loading p {
font-size: 0.75em; font-size: 0.75em;
font-weight: 500; font-weight: 500;
text-transform: uppercase; text-transform: uppercase;
opacity: 0.35; opacity: 0.35;
} }
/* h1#title { /* h1#title {
padding-left: 1rem; padding-left: 1rem;
} */ } */
body { body {
width: 100%; width: 100%;
padding-bottom: 20px; padding-bottom: 20px;
} }
@media screen and (min-device-width: 767px) { @media screen and (min-device-width: 767px) {
body { body {
margin: 0 auto; margin: 0 auto;
max-width: 414px; max-width: 414px;
} }
} }
.hidden { .hidden {
opacity: 0; opacity: 0;
pointer-events: none; pointer-events: none;
} }
#top { #top {
position: fixed; position: fixed;
z-index: 5; z-index: 5;
left: 0; left: 0;
right: 0; right: 0;
} }
#title { #title {
margin-bottom: 0.25em; margin-bottom: 0.25em;
} }
#main>p:first-of-type { #main>p:first-of-type {
text-transform: uppercase; text-transform: uppercase;
font-weight: 500; font-weight: 500;
font-size: 0.9em; font-size: 0.9em;
opacity: 0.5; opacity: 0.5;
padding-left: 1rem; padding-left: 1rem;
margin-top: 1rem; margin-top: 1rem;
} }
/* Navigation bar */ /* Navigation bar */
#nav-bar { #nav-bar {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
border-bottom: 0.1px solid var(--color-separator); border-bottom: 0.1px solid var(--color-separator);
background-color: var(--color-transparent); background-color: var(--color-transparent);
-webkit-backdrop-filter: saturate(100%) blur(30px); -webkit-backdrop-filter: saturate(100%) blur(30px);
backdrop-filter: saturate(100%) blur(20px); backdrop-filter: saturate(100%) blur(20px);
max-width: 414px; max-width: 414px;
margin: 0 auto; margin: 0 auto;
padding: 0.25em 0.75em; padding: 0.25em 0.75em;
z-index: 2; z-index: 2;
} }
#nav-bar #title { #nav-bar #title {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
align-items: center; align-items: center;
gap: 6px; gap: 6px;
min-height: 2.5em; min-height: 2.5em;
margin: 0; margin: 0;
} }
#nav-bar #title>p { #nav-bar #title>p {
font-weight: 600; font-weight: 600;
} }
#nav-bar #title>img { #nav-bar #title>img {
max-height: 2em; max-height: 2em;
border-radius: 0.4em; border-radius: 0.4em;
} }
#nav-bar #back { #nav-bar #back {
cursor: pointer; cursor: pointer;
} }
#nav-bar #back .bi { #nav-bar #back .bi {
margin-left: -8px; margin-left: -8px;
-webkit-text-stroke: 1px; -webkit-text-stroke: 1px;
font-size: 1.3em; font-size: 1.3em;
} }
/* Main */ /* Main */
#main { #main {
/* padding: 1em; */ /* padding: 1em; */
padding-top: 3.55rem; padding-top: 3.55rem;
} }
.item { .item {
margin: 1rem 0; margin: 1rem 0;
} }
/* Section header */ /* Section header */
.header { .header {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
padding: 0 1rem; padding: 0 1rem;
} }
/* News */ /* News */
#news-items { #news-items {
display: grid; display: grid;
height: 100%; height: 100%;
gap: 1em; gap: 1em;
grid-auto-columns: 95%; grid-auto-columns: 95%;
grid-auto-flow: column; grid-auto-flow: column;
overflow-x: scroll; overflow-x: scroll;
padding: 1rem; padding: 1rem;
} }
#news-items.one { #news-items.one {
grid-auto-columns: 100% !important; grid-auto-columns: 100% !important;
} }
#news .item { #news .item {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
justify-content: center; justify-content: center;
border-radius: 1.5em; border-radius: 1.5em;
overflow: hidden; overflow: hidden;
min-width: 100%; min-width: 100%;
height: 100%; height: 100%;
margin: 0; margin: 0;
} }
#news .item>.text { #news .item>.text {
margin: 1.5em; margin: 1.5em;
color: #fff; color: #fff;
} }
#news .item>.text>p { #news .item>.text>p {
opacity: 0.75; opacity: 0.75;
font-size: 0.9em; font-size: 0.9em;
} }
#news .item .image-wrapper { #news .item .image-wrapper {
max-height: 15.15em; max-height: 15.15em;
overflow: hidden; overflow: hidden;
} }
#news img { #news img {
width: 100%; width: 100%;
height: auto; height: auto;
display: block; display: block;
} }
/* App header */ /* App header */
#apps.section .item { #apps.section .item {
padding: 0 1rem; padding: 0 1rem;
} }
.app-header { .app-header {
position: relative; position: relative;
display: flex; display: flex;
} }
.app-header>.content { .app-header>.content {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
align-items: center; align-items: center;
width: 100%; width: 100%;
padding: 1rem; padding: 1rem;
} }
.app-header img { .app-header img {
display: block; display: block;
border-radius: 13.5px; border-radius: 13.5px;
max-width: 64px; max-width: 64px;
} }
.app-header .background { .app-header .background {
position: absolute; position: absolute;
background-color: var(--accent-color); background-color: var(--accent-color);
opacity: 0.2; opacity: 0.2;
border-radius: 1.5em; border-radius: 1.5em;
width: 100%; width: 100%;
height: 100%; height: 100%;
z-index: -1; z-index: -1;
} }
.app-header>.content>.right { .app-header>.content>.right {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
width: 100%; width: 100%;
margin-left: 0.65em; margin-left: 0.65em;
} }
.app-header>.content .text { .app-header>.content .text {
margin-right: 0.5em; margin-right: 0.5em;
} }
.app-header>.content .text>.title { .app-header>.content .text>.title {
font-weight: 600; font-weight: 600;
font-size: 1rem; font-size: 1rem;
} }
.app-header>.content .text>.subtitle { .app-header>.content .text>.subtitle {
opacity: 0.5; opacity: 0.5;
font-size: 0.85em; font-size: 0.85em;
} }
/* About */ /* About */
#about a:visited { #about a:visited {
color: var(--accent-color) color: var(--accent-color)
} }
#about.section .item { #about.section .item {
padding: 0 1rem; padding: 0 1rem;
} }
#about p { #about p {
word-wrap: break-word; word-wrap: break-word;
} }
/* Buttons */ /* Buttons */
button.uibutton { button.uibutton {
min-width: 78px; min-width: 78px;
height: 32px; height: 32px;
padding: 0 12px; padding: 0 12px;
font-size: 15px; font-size: 15px;
font-weight: 700; font-weight: 700;
text-transform: uppercase; text-transform: uppercase;
border: none; border: none;
border-radius: 20px; border-radius: 20px;
color: white; color: white;
background-color: var(--accent-color); background-color: var(--accent-color);
cursor: pointer; cursor: pointer;
} }
button.uibutton:active { button.uibutton:active {
opacity: 0.8; opacity: 0.8;
} }
/* Links */ /* Links */
a { a {
cursor: pointer; cursor: pointer;
text-decoration: none; text-decoration: none;
color: var(--accent-color) color: var(--accent-color)
} }
a>button { a>button {
cursor: pointer; cursor: pointer;
} }
@media (hover:hover) { @media (hover:hover) {
a:hover { a:hover {
opacity: 0.75; opacity: 0.75;
} }
} }
.header a, .header a,
#nav-bar #back { #nav-bar #back {
display: flex; display: flex;
align-items: center; align-items: center;
font-size: 1.05em; font-size: 1.05em;
font-weight: 450; font-weight: 450;
border: none; border: none;
background: unset; background: unset;
padding: 0; padding: 0;
color: var(--accent-color); color: var(--accent-color);
} }
/* Badges */ /* Badges */
.badge { .badge {
margin-left: 0.05rem !important; margin-left: 0.05rem !important;
margin-right: 0.05rem !important; margin-right: 0.05rem !important;
padding: 0.5px 6.5px; padding: 0.5px 6.5px;
font-size: 10px; font-size: 10px;
line-height: 1.3333733333; line-height: 1.3333733333;
font-weight: 700; font-weight: 700;
border-radius: 12px; border-radius: 12px;
border-width: 1px; border-width: 1px;
border-style: solid; border-style: solid;
box-sizing: border-box; box-sizing: border-box;
white-space: nowrap; white-space: nowrap;
display: inline-block; display: inline-block;
background: transparent; background: transparent;
text-transform: uppercase; text-transform: uppercase;
vertical-align: middle; vertical-align: middle;
color: white; color: white;
border-color: transparent; border-color: transparent;
} }
.beta.badge { .beta.badge {
margin-bottom: 2px; margin-bottom: 2px;
background-color: #f5a10d; background-color: #f5a10d;
} }
.beta.badge::before { .beta.badge::before {
content: "Beta"; content: "Beta";
} }
.small.badge { .small.badge {
font-size: 8px; font-size: 8px;
} }

View File

@@ -1,46 +1,46 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="css/shared.css"> <link rel="stylesheet" href="css/shared.css">
<link rel="stylesheet" href="css/uibanner.css"> <link rel="stylesheet" href="css/uibanner.css">
</head> </head>
<body class="loading"> <body class="loading">
<div id="loading"> <div id="loading">
<img src="img/loading.gif" alt="loading"> <img src="img/loading.gif" alt="loading">
<p>Loading</p> <p>Loading</p>
</div> </div>
<!-- Add to AltStore banner --> <!-- Add to AltStore banner -->
<div id="top"></div> <div id="top"></div>
<div id="main"> <div id="main">
<p>Now viewing</p> <p>Now viewing</p>
<div class="header"> <div class="header">
<h1 id="title">altsource-v2</h1> <h1 id="title">altsource-v2</h1>
<a href="search.html"><i class="bi bi-search"></i></a> <a href="search.html"><i class="bi bi-search"></i></a>
</div> </div>
<div id="news" class="section"> <div id="news" class="section">
<div class="header"> <div class="header">
<h2>News</h2> <h2>News</h2>
<a href="search.html">View All</a> <a href="search.html">View All</a>
</div> </div>
<div id="news-items"></div> <div id="news-items"></div>
</div> </div>
<div id="apps" class="section"> <div id="apps" class="section">
<div class="header"> <div class="header">
<h2>Featured Apps</h2> <h2>Featured Apps</h2>
<a href="search.html">View All Apps</a> <a href="search.html">View All Apps</a>
</div> </div>
</div> </div>
<div id="about" class="section"> <div id="about" class="section">
<div class="header"> <div class="header">
<h2>About</h2> <h2>About</h2>
</div> </div>
</div> </div>
</div> </div>
<script src="js/shared.js"></script> <script src="js/shared.js"></script>
<script src="js/index.js"></script> <script src="js/index.js"></script>
<script src="js/main.js"></script> <script src="js/main.js"></script>
</body> </body>
</html> </html>

304
js/app.js
View File

@@ -2,181 +2,181 @@ if (!urlSearchParams.has('id')) exit();
const bundleId = urlSearchParams.get('id'); const bundleId = urlSearchParams.get('id');
(function () { (function () {
// Hide/show navigation bar title & install button // Hide/show navigation bar title & install button
let hidden = false; let hidden = false;
window.onscroll = function (e) { window.onscroll = function (e) {
const appName = document.querySelector(".app-header .text>.title"); const appName = document.querySelector(".app-header .text>.title");
const title = document.getElementById("title"); const title = document.getElementById("title");
const button = document.querySelector("#nav-bar .install"); const button = document.querySelector("#nav-bar .install");
if (hidden && appName.getBoundingClientRect().y >= 72) { // App name not visible if (hidden && appName.getBoundingClientRect().y >= 72) { // App name not visible
hidden = false; hidden = false;
title.classList.add("hidden"); title.classList.add("hidden");
button.classList.add("hidden"); button.classList.add("hidden");
button.disaled = true; button.disaled = true;
} else if (!hidden && appName.getBoundingClientRect().y < 72) { } else if (!hidden && appName.getBoundingClientRect().y < 72) {
hidden = true; hidden = true;
title.classList.remove("hidden"); title.classList.remove("hidden");
button.classList.remove("hidden"); button.classList.remove("hidden");
button.disaled = false; button.disaled = false;
} }
} }
})(); })();
function main(json) { function main(json) {
const app = getAppWithBundleId(bundleId); const app = getAppWithBundleId(bundleId);
if (!app) exit(); if (!app) exit();
// Set tab title // Set tab title
document.title = `${app.name} - ${json.name}`; document.title = `${app.name} - ${json.name}`;
const tintColor = `#${app.tintColor?.replaceAll("#", "")}`; const tintColor = `#${app.tintColor?.replaceAll("#", "")}`;
// Set tint color // Set tint color
if (tintColor) document.querySelector(':root').style.setProperty("--app-tint-color", `${tintColor}`); if (tintColor) document.querySelector(':root').style.setProperty("--app-tint-color", `${tintColor}`);
// Tint back button // Tint back button
document.getElementById("back").style.color = tintColor; document.getElementById("back").style.color = tintColor;
// Set up install buttons // Set up install buttons
document.querySelectorAll("a.install").forEach(button => { document.querySelectorAll("a.install").forEach(button => {
button.href = `altstore://install?url=${app.downloadURL}`; button.href = `altstore://install?url=${app.downloadURL}`;
}); });
// Set up download button // Set up download button
document.getElementById("download").href = app.downloadURL; document.getElementById("download").href = app.downloadURL;
// //
// Navigation bar // Navigation bar
const navigationBar = document.getElementById("nav-bar"); const navigationBar = document.getElementById("nav-bar");
// Title // Title
navigationBar.querySelector("#title>p").textContent = app.name; navigationBar.querySelector("#title>p").textContent = app.name;
// App icon // App icon
navigationBar.querySelector("#title>img").src = app.iconURL; navigationBar.querySelector("#title>img").src = app.iconURL;
// Install button // Install button
navigationBar.querySelector(".uibutton").style.backgroundColor = `${tintColor}`; navigationBar.querySelector(".uibutton").style.backgroundColor = `${tintColor}`;
// //
// App header // App header
const appHeader = document.querySelector("#main .app-header"); const appHeader = document.querySelector("#main .app-header");
// Icon // Icon
appHeader.querySelector("img").src = app.iconURL; appHeader.querySelector("img").src = app.iconURL;
// App name // App name
appHeader.querySelector(".title").textContent = app.name; appHeader.querySelector(".title").textContent = app.name;
// Developer name // Developer name
appHeader.querySelector(".subtitle").textContent = app.developerName; appHeader.querySelector(".subtitle").textContent = app.developerName;
// Install button // Install button
appHeader.querySelector(".uibutton").style.backgroundColor = tintColor; appHeader.querySelector(".uibutton").style.backgroundColor = tintColor;
// Background // Background
appHeader.querySelector(".background").style.backgroundColor = tintColor; appHeader.querySelector(".background").style.backgroundColor = tintColor;
const more = ` const more = `
<a id="more" onclick="revealTruncatedText(this);"> <a id="more" onclick="revealTruncatedText(this);">
<button style="color: ${tintColor};">more</button> <button style="color: ${tintColor};">more</button>
</a>`; </a>`;
this.revealTruncatedText = moreButton => { this.revealTruncatedText = moreButton => {
const textId = moreButton.parentNode.id; const textId = moreButton.parentNode.id;
const text = document.getElementById(textId); const text = document.getElementById(textId);
text.style.display = "block"; text.style.display = "block";
text.style.overflow = "auto"; text.style.overflow = "auto";
text.style.webkitLineClamp = "none"; text.style.webkitLineClamp = "none";
text.style.lineClamp = "none"; text.style.lineClamp = "none";
text.removeChild(moreButton) text.removeChild(moreButton)
} }
// //
// Preview // Preview
const preview = document.getElementById("preview"); const preview = document.getElementById("preview");
// Subtitle // Subtitle
preview.querySelector("#subtitle").textContent = app.subtitle; preview.querySelector("#subtitle").textContent = app.subtitle;
// Screenshots // Screenshots
app.screenshotURLs.forEach(url => { app.screenshotURLs.forEach(url => {
preview.querySelector("#screenshots").insertAdjacentHTML("beforeend", `<img src="${url}" alt="">`); preview.querySelector("#screenshots").insertAdjacentHTML("beforeend", `<img src="${url}" alt="">`);
}); });
// Description // Description
const previewDescription = preview.querySelector("#description"); const previewDescription = preview.querySelector("#description");
previewDescription.innerHTML = formatString(app.localizedDescription); previewDescription.innerHTML = formatString(app.localizedDescription);
if (previewDescription.scrollHeight > previewDescription.clientHeight) if (previewDescription.scrollHeight > previewDescription.clientHeight)
previewDescription.insertAdjacentHTML("beforeend", more); previewDescription.insertAdjacentHTML("beforeend", more);
// //
// Version info // Version info
const versionDateElement = document.getElementById("version-date"); const versionDateElement = document.getElementById("version-date");
const versionNumberElement = document.getElementById("version"); const versionNumberElement = document.getElementById("version");
const versionSizeElement = document.getElementById("version-size"); const versionSizeElement = document.getElementById("version-size");
const versionDescriptionElement = document.getElementById("version-description"); const versionDescriptionElement = document.getElementById("version-description");
const versionDate = new Date(app.versionDate), const versionDate = new Date(app.versionDate),
month = versionDate.toUTCString().split(" ")[2], month = versionDate.toUTCString().split(" ")[2],
date = versionDate.getDate(); date = versionDate.getDate();
const today = new Date(); const today = new Date();
const msPerDay = 60 * 60 * 24 * 1000; const msPerDay = 60 * 60 * 24 * 1000;
const msDifference = today.valueOf() - versionDate.valueOf(); const msDifference = today.valueOf() - versionDate.valueOf();
// Version date // Version date
versionDateElement.textContent = versionDate.valueOf() ? `${month} ${date}, ${versionDate.getFullYear()}` : app.versionDate.split("T")[0]; versionDateElement.textContent = versionDate.valueOf() ? `${month} ${date}, ${versionDate.getFullYear()}` : app.versionDate.split("T")[0];
if (msDifference <= msPerDay && today.getDate() == versionDate.getDate()) if (msDifference <= msPerDay && today.getDate() == versionDate.getDate())
versionDateElement.textContent = "Today"; versionDateElement.textContent = "Today";
else if (msDifference <= msPerDay * 2) else if (msDifference <= msPerDay * 2)
versionDateElement.textContent = "Yesterday"; versionDateElement.textContent = "Yesterday";
// Version number // Version number
versionNumberElement.textContent = `Version ${app.version}`; versionNumberElement.textContent = `Version ${app.version}`;
// Version size // Version size
const units = ["B", "KB", "MB", "GB"]; const units = ["B", "KB", "MB", "GB"];
var appSize = app.size, i = 0; var appSize = app.size, i = 0;
while (appSize > 1024) { i++; while (appSize > 1024) { i++;
appSize = parseFloat(appSize / 1024).toFixed(1); appSize = parseFloat(appSize / 1024).toFixed(1);
} }
versionSizeElement.textContent = `${appSize} ${units[i]}`; versionSizeElement.textContent = `${appSize} ${units[i]}`;
// Version description // Version description
versionDescriptionElement.innerHTML = formatString(app.versionDescription); versionDescriptionElement.innerHTML = formatString(app.versionDescription);
if (versionDescriptionElement.scrollHeight > versionDescriptionElement.clientHeight) if (versionDescriptionElement.scrollHeight > versionDescriptionElement.clientHeight)
versionDescriptionElement.insertAdjacentHTML("beforeend", more); versionDescriptionElement.insertAdjacentHTML("beforeend", more);
// //
// Permissions // Permissions
const permissions = document.getElementById("permissions"); const permissions = document.getElementById("permissions");
// If permissions specified // If permissions specified
if (app.permissions) if (app.permissions)
// Remove placeholder permission // Remove placeholder permission
permissions.querySelector(".permission").remove(); permissions.querySelector(".permission").remove();
else return; else return;
app.permissions?.forEach(permission => { app.permissions?.forEach(permission => {
var permissionType, icon; var permissionType, icon;
switch (permission.type) { switch (permission.type) {
case "background-audio": case "background-audio":
permissionType = "Background Audio"; permissionType = "Background Audio";
icon = "volume-up-fill"; icon = "volume-up-fill";
break; break;
case "background-fetch": case "background-fetch":
permissionType = "Background Fetch"; permissionType = "Background Fetch";
icon = "arrow-repeat" icon = "arrow-repeat"
break; break;
case "photos": case "photos":
permissionType = "Photos" permissionType = "Photos"
icon = "image-fill"; icon = "image-fill";
break; break;
default: default:
permissionType = permission.type.replaceAll("-", " "); permissionType = permission.type.replaceAll("-", " ");
icon = "gear-wide-connected"; icon = "gear-wide-connected";
break; break;
} }
permissions.insertAdjacentHTML("beforeend", ` permissions.insertAdjacentHTML("beforeend", `
<div class="permission"> <div class="permission">
<i class="bi-${icon}" style="color: ${tintColor};"></i> <i class="bi-${icon}" style="color: ${tintColor};"></i>
<div class="text"> <div class="text">
<p class="title">${permissionType}</p> <p class="title">${permissionType}</p>
<p class="description">${permission.usageDescription ?? "No description provided."}</p> <p class="description">${permission.usageDescription ?? "No description provided."}</p>
</div> </div>
</div>`); </div>`);
}); });
} }
function exit() { function exit() {
window.location.replace(`home.html?source=${sourceURL}`); window.location.replace(`home.html?source=${sourceURL}`);
} }

View File

@@ -1,31 +1,31 @@
insertNavigationBar("All Apps"); insertNavigationBar("All Apps");
function main(json) { function main(json) {
// Set tab title // Set tab title
document.title = `Apps - ${json.name}`; document.title = `Apps - ${json.name}`;
// Sort apps in decending order of version date (newest first) // Sort apps in decending order of version date (newest first)
json.apps.sort((a, b) => (new Date(b.versionDate)).valueOf() - (new Date(a.versionDate)).valueOf()); json.apps.sort((a, b) => (new Date(b.versionDate)).valueOf() - (new Date(a.versionDate)).valueOf());
// Create & insert app items // Create & insert app items
json.apps.forEach(app => { json.apps.forEach(app => {
if (app.beta) return; // Ignore beta apps if (app.beta) return; // Ignore beta apps
let html = ` let html = `
<div class="app-container"> <div class="app-container">
${appHeaderHTML(app) } ${appHeaderHTML(app) }
<p style="text-align: center; font-size: 0.9em;">${app.subtitle ?? ""}</p>`; <p style="text-align: center; font-size: 0.9em;">${app.subtitle ?? ""}</p>`;
if (app.screenshotURLs) { if (app.screenshotURLs) {
html += ` html += `
<div class="screenshots">`; <div class="screenshots">`;
for (let i = 0; i < app.screenshotURLs.length, i < 2; i++) html += ` for (let i = 0; i < app.screenshotURLs.length, i < 2; i++) html += `
<img src="${app.screenshotURLs[i]}" class="screenshot">`; <img src="${app.screenshotURLs[i]}" class="screenshot">`;
html += ` html += `
</div>`; </div>`;
} }
html += ` html += `
</div>`; </div>`;
document.getElementById("apps").insertAdjacentHTML("beforeend", html); document.getElementById("apps").insertAdjacentHTML("beforeend", html);
}); });
} }

View File

@@ -1,56 +1,56 @@
function main(json) { function main(json) {
// Set "View All News" link // Set "View All News" link
document.querySelector("#news a").href = `news.html?source=${sourceURL}`; document.querySelector("#news a").href = `news.html?source=${sourceURL}`;
// Set "View All Apps" link // Set "View All Apps" link
document.querySelector("#apps a").href = `apps.html?source=${sourceURL}`; document.querySelector("#apps a").href = `apps.html?source=${sourceURL}`;
// Set tab title // Set tab title
document.title = json.name; document.title = json.name;
// Set page title // Set page title
document.getElementById("title").innerText = json.name; document.getElementById("title").innerText = json.name;
// //
// News // News
if (json.news && json.news.length >= 1) { if (json.news && json.news.length >= 1) {
// Sort news in decending order of date (latest first) // Sort news in decending order of date (latest first)
json.news.sort((a, b) => // If b < a json.news.sort((a, b) => // If b < a
(new Date(b.date)).valueOf() - (new Date(a.date)).valueOf()); (new Date(b.date)).valueOf() - (new Date(a.date)).valueOf());
if (json.news.length == 1) { if (json.news.length == 1) {
document.getElementById("news-items").insertAdjacentHTML("beforeend", newsItemHTML(json.news[0], true)); document.getElementById("news-items").insertAdjacentHTML("beforeend", newsItemHTML(json.news[0], true));
document.getElementById("news-items").classList.add("one"); document.getElementById("news-items").classList.add("one");
} else for (let i = 0; i < 5 && i < json.news.length; i++) } else for (let i = 0; i < 5 && i < json.news.length; i++)
document.getElementById("news-items").insertAdjacentHTML("beforeend", newsItemHTML(json.news[i], true)); document.getElementById("news-items").insertAdjacentHTML("beforeend", newsItemHTML(json.news[i], true));
} else document.getElementById("news").remove(); } else document.getElementById("news").remove();
// Sort apps in descending order of version date // Sort apps in descending order of version date
json.apps.sort((a, b) => (new Date(b.versionDate)).valueOf() - (new Date(a.versionDate)).valueOf()); json.apps.sort((a, b) => (new Date(b.versionDate)).valueOf() - (new Date(a.versionDate)).valueOf());
// //
// Featured apps // Featured apps
let count = 1; let count = 1;
json.apps.forEach(app => { json.apps.forEach(app => {
// Max: 3 featured apps if not specified // Max: 3 featured apps if not specified
if (count > 3) return; if (count > 3) return;
// Ignore beta apps // Ignore beta apps
if (app.beta) return; if (app.beta) return;
// If there are featured apps, ignore non-featured apps // If there are featured apps, ignore non-featured apps
if (json.featuredApps && !json.featuredApps.includes(app.bundleIdentifier)) return; if (json.featuredApps && !json.featuredApps.includes(app.bundleIdentifier)) return;
document.getElementById("apps").insertAdjacentHTML("beforeend", appHeaderHTML(app)); document.getElementById("apps").insertAdjacentHTML("beforeend", appHeaderHTML(app));
count++; count++;
}); });
// //
// About // About
var description = formatString(json.description); var description = formatString(json.description);
if (description) document.getElementById("about").insertAdjacentHTML("beforeend", ` if (description) document.getElementById("about").insertAdjacentHTML("beforeend", `
<div class="item"> <div class="item">
<p>${description}</p> <p>${description}</p>
</div> </div>
`); `);
else document.getElementById("about").remove(); else document.getElementById("about").remove();
} }

View File

@@ -1,44 +1,44 @@
(function () { (function () {
// If no source // If no source
if (!urlSearchParams.has('source')) if (!urlSearchParams.has('source'))
search(); search();
// If source is not a valid HTTP URL // If source is not a valid HTTP URL
else if (!isValidHTTPURL(sourceURL)) { else if (!isValidHTTPURL(sourceURL)) {
alert("Invalid HTTP URL."); alert("Invalid HTTP URL.");
search(); search();
} else insertAddToAltStoreBanner(); } else insertAddToAltStoreBanner();
})(); })();
fetch(sourceURL) fetch(sourceURL)
.then(response => response.json()) .then(response => response.json())
.then(json => { .then(json => {
// Set tint color // Set tint color
const tintColor = json.tintColor?.replaceAll("#", ""); const tintColor = json.tintColor?.replaceAll("#", "");
if (tintColor) setTintColor(tintColor); if (tintColor) setTintColor(tintColor);
setApps(json.apps); setApps(json.apps);
main(json); main(json);
waitForAllImagesToLoad(); waitForAllImagesToLoad();
}) })
.catch(error => console.error("An error occurred.", error)); .catch(error => console.error("An error occurred.", error));
function waitForAllImagesToLoad() { function waitForAllImagesToLoad() {
const allImages = document.querySelectorAll("img"); const allImages = document.querySelectorAll("img");
var count = 0; var count = 0;
allImages.forEach(image => { allImages.forEach(image => {
// New img element that won't be rendered to the DOM // New img element that won't be rendered to the DOM
var newImage = document.createElement("img"); var newImage = document.createElement("img");
// Attach load listener // Attach load listener
newImage.addEventListener("load", loaded); newImage.addEventListener("load", loaded);
// Set src // Set src
newImage.src = image.src; newImage.src = image.src;
}); });
function loaded() { function loaded() {
if (++count == allImages.length) { if (++count == allImages.length) {
document.querySelector("body").classList.remove("loading"); document.querySelector("body").classList.remove("loading");
document.getElementById("loading").remove(); document.getElementById("loading").remove();
} }
} }
} }

View File

@@ -1,12 +1,12 @@
insertNavigationBar("All News"); insertNavigationBar("All News");
function main(json) { function main(json) {
// Set tab title // Set tab title
document.title = `News - ${json.name}`; document.title = `News - ${json.name}`;
// Sort news by latest // Sort news by latest
json.news.sort((a, b) => (new Date(b.date)).valueOf() - (new Date(a.date)).valueOf()); json.news.sort((a, b) => (new Date(b.date)).valueOf() - (new Date(a.date)).valueOf());
// Create & insert news items // Create & insert news items
json.news.forEach(news => document.getElementById("news").insertAdjacentHTML("beforeend", newsItemHTML(news))); json.news.forEach(news => document.getElementById("news").insertAdjacentHTML("beforeend", newsItemHTML(news)));
} }

View File

@@ -1,19 +1,19 @@
(function main() { (function main() {
const success = url => window.location.replace(`index.html?source=${url}`); const success = url => window.location.replace(`index.html?source=${url}`);
// If valid source provided // If valid source provided
if (urlSearchParams.has('source') && isValidHTTPURL(sourceURL)) if (urlSearchParams.has('source') && isValidHTTPURL(sourceURL))
success(sourceURL); success(sourceURL);
const textField = document.querySelector("input"); const textField = document.querySelector("input");
textField.addEventListener("keypress", function (event) { textField.addEventListener("keypress", function (event) {
if (event.key === "Enter") { if (event.key === "Enter") {
event.preventDefault(); event.preventDefault();
const url = textField.value; const url = textField.value;
if (!isValidHTTPURL(url)) if (!isValidHTTPURL(url))
alert("Invalid HTTP URL."); alert("Invalid HTTP URL.");
else success(url); else success(url);
} }
}); });
})(); })();

View File

@@ -4,132 +4,132 @@ const sourceURL = urlSearchParams.get('source');
const urlRegex = /(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig; const urlRegex = /(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig;
(function (global) { (function (global) {
var apps; var apps;
global.setApps = array => global.setApps = array =>
apps = array; apps = array;
global.getAppWithBundleId = bundleId => global.getAppWithBundleId = bundleId =>
apps?.find(app => app.bundleIdentifier == bundleId) ?? undefined; apps?.find(app => app.bundleIdentifier == bundleId) ?? undefined;
setUpBackButton(); setUpBackButton();
})(this); })(this);
const newsItemHTML = (news, minimal = false) => ` const newsItemHTML = (news, minimal = false) => `
<div class="news-item-wrapper"> ${news.url ? <div class="news-item-wrapper"> ${news.url ?
"<a href='" + news.url + "'>" : ""} "<a href='" + news.url + "'>" : ""}
<div class="item" style="background-color: #${news.tintColor};"> <div class="item" style="background-color: #${news.tintColor};">
<div class="text"> <div class="text">
<h3>${news.title}</h3> <h3>${news.title}</h3>
<p>${news.caption}</p> <p>${news.caption}</p>
</div>${news.imageURL && !minimal ? </div>${news.imageURL && !minimal ?
"<div class='image-wrapper'>" + "<div class='image-wrapper'>" +
"<img src='" + news.imageURL + "'>" + "<img src='" + news.imageURL + "'>" +
"</div>" : ""} "</div>" : ""}
</div> ${news.url ? </div> ${news.url ?
"</a>" : ""} ${news.appID && !minimal ? "</a>" : ""} ${news.appID && !minimal ?
appHeaderHTML(getAppWithBundleId(news.appID)) ?? "" : ""} appHeaderHTML(getAppWithBundleId(news.appID)) ?? "" : ""}
</div>`; </div>`;
const appHeaderHTML = app => app ? ` const appHeaderHTML = app => app ? `
<div class="item"> <div class="item">
<div class="app-header"> <div class="app-header">
<div class="content"> <div class="content">
<img src="${app.iconURL}" alt=""> <img src="${app.iconURL}" alt="">
<div class="right"> <div class="right">
<div class="text"> <div class="text">
<p class="title">${app.name}</p> <p class="title">${app.name}</p>
<p class="subtitle">${app.developerName}</p> <p class="subtitle">${app.developerName}</p>
</div> </div>
<a href="app.html?source=${sourceURL}&id=${app.bundleIdentifier}"> <a href="app.html?source=${sourceURL}&id=${app.bundleIdentifier}">
<button class="uibutton" style="background-color: #${app.tintColor};">View</button> <button class="uibutton" style="background-color: #${app.tintColor};">View</button>
</a> </a>
</div> </div>
</div> </div>
<div class="background" style="background-color: #${app.tintColor};"></div> <div class="background" style="background-color: #${app.tintColor};"></div>
</div> </div>
</div>` : undefined; </div>` : undefined;
function insertAddToAltStoreBanner() { function insertAddToAltStoreBanner() {
document.getElementById("top")?.insertAdjacentHTML("afterbegin", ` document.getElementById("top")?.insertAdjacentHTML("afterbegin", `
<div class="uibanner"> <div class="uibanner">
<img src="https://user-images.githubusercontent.com/705880/65270980-1eb96f80-dad1-11e9-9367-78ccd25ceb02.png" alt="altstore-icon" class="icon"> <img src="https://user-images.githubusercontent.com/705880/65270980-1eb96f80-dad1-11e9-9367-78ccd25ceb02.png" alt="altstore-icon" class="icon">
<div class="content"> <div class="content">
<div class="text-container"> <div class="text-container">
<p class="title-text">AltStore <span class="small beta badge"></span></p> <p class="title-text">AltStore <span class="small beta badge"></span></p>
<p class="detail-text"> <p class="detail-text">
Add this source to AltStore to receive app updates (requires AltStore beta) Add this source to AltStore to receive app updates (requires AltStore beta)
</p> </p>
</div> </div>
<a href="altstore://source?url=${sourceURL}"> <a href="altstore://source?url=${sourceURL}">
<button>Add</button> <button>Add</button>
</a> </a>
</div> </div>
</div>`); </div>`);
} }
function insertNavigationBar(title) { function insertNavigationBar(title) {
document.getElementById("top")?.insertAdjacentHTML("beforeend", ` document.getElementById("top")?.insertAdjacentHTML("beforeend", `
<div id="nav-bar"> <div id="nav-bar">
<button id="back" type="button"> <button id="back" type="button">
<i class="bi bi-chevron-left"></i> <i class="bi bi-chevron-left"></i>
Back Back
</button> </button>
<div id="title"> <div id="title">
<p>${title ?? ""}</p> <p>${title ?? ""}</p>
</div> </div>
<button id="back" class="hidden"> <button id="back" class="hidden">
<i class="bi bi-chevron-left"></i> <i class="bi bi-chevron-left"></i>
Back Back
</button> </button>
</div>`); </div>`);
setUpBackButton(); setUpBackButton();
} }
// https://stackoverflow.com/a/43467144/19227228 // https://stackoverflow.com/a/43467144/19227228
function isValidHTTPURL(string) { function isValidHTTPURL(string) {
var url; var url;
try { try {
url = new URL(string); url = new URL(string);
} catch (error) { } catch (error) {
console.error("An error occurred.", error); console.error("An error occurred.", error);
return false; return false;
} }
return url.protocol == "http:" || url.protocol == "https:"; return url.protocol == "http:" || url.protocol == "https:";
} }
function formatString(string) { function formatString(string) {
if (!string) return undefined; if (!string) return undefined;
// URLs // URLs
const urlArray = string.match(urlRegex); const urlArray = string.match(urlRegex);
// const urlSet = [...new Set(urlArray)]; // Converting to set to remove duplicates // const urlSet = [...new Set(urlArray)]; // Converting to set to remove duplicates
var result = ""; var result = "";
urlArray?.forEach(url => { urlArray?.forEach(url => {
string = string.replace(url, `<a href="${url}">${url}</a>`) string = string.replace(url, `<a href="${url}">${url}</a>`)
// Remove formatted substring so it won't get formatted again (prevents <a> tag within the href attribute another <a> tag) // Remove formatted substring so it won't get formatted again (prevents <a> tag within the href attribute another <a> tag)
let endIndexOfClosingTag = string.indexOf("</a>") + 4; let endIndexOfClosingTag = string.indexOf("</a>") + 4;
let formattedSubstring = string.substring(0, endIndexOfClosingTag); let formattedSubstring = string.substring(0, endIndexOfClosingTag);
result += formattedSubstring; result += formattedSubstring;
string = string.replace(formattedSubstring, ""); string = string.replace(formattedSubstring, "");
}); });
result += string; result += string;
// New lines // New lines
return result.replaceAll("\n", "<br>"); return result.replaceAll("\n", "<br>");
} }
function setTintColor(color) { function setTintColor(color) {
document.querySelector(':root')?.style.setProperty("--accent-color", `#${color}`); document.querySelector(':root')?.style.setProperty("--accent-color", `#${color}`);
} }
function setUpBackButton() { function setUpBackButton() {
document.getElementById("back")?.addEventListener("click", () => history.back(1)); document.getElementById("back")?.addEventListener("click", () => history.back(1));
} }
function search() { function search() {
window.location.replace("search.html"); window.location.replace("search.html");
} }
const $ = selector => selector.startsWith("#") && !selector.includes(".") && !selector.includes(" ") const $ = selector => selector.startsWith("#") && !selector.includes(".") && !selector.includes(" ")
? document.getElementById(selector.substring(1)) ? document.getElementById(selector.substring(1))
: document.querySelectorAll(selector); : document.querySelectorAll(selector);

View File

@@ -1,25 +1,25 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="css/shared.css"> <link rel="stylesheet" href="css/shared.css">
<link rel="stylesheet" href="css/uibanner.css"> <link rel="stylesheet" href="css/uibanner.css">
<link rel="stylesheet" href="css/news.css"> <link rel="stylesheet" href="css/news.css">
</head> </head>
<body class="loading"> <body class="loading">
<div id="loading"> <div id="loading">
<img src="img/loading.gif" alt="loading"> <img src="img/loading.gif" alt="loading">
<p>Loading</p> <p>Loading</p>
</div> </div>
<!-- Add to AltStore banner & navigation bar --> <!-- Add to AltStore banner & navigation bar -->
<div id="top"></div> <div id="top"></div>
<div id="main"> <div id="main">
<div id="news"></div> <div id="news"></div>
</div> </div>
<script src="js/shared.js"></script> <script src="js/shared.js"></script>
<script src="js/news.js"></script> <script src="js/news.js"></script>
<script src="js/main.js"></script> <script src="js/main.js"></script>
</body> </body>
</html> </html>

View File

@@ -1,61 +1,61 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="css/shared.css"> <link rel="stylesheet" href="css/shared.css">
<link rel="stylesheet" href="css/search.css"> <link rel="stylesheet" href="css/search.css">
</head> </head>
<body> <body>
<div id="main"> <div id="main">
<h1 id="title">AltSource Viewer</h1> <h1 id="title">AltSource Viewer</h1>
<div class="textfield"> <div class="textfield">
<input type="text" placeholder="Source URL"> <input type="text" placeholder="Source URL">
</div> </div>
<div id="suggestions" class="section"> <div id="suggestions" class="section">
<div class="header"> <div class="header">
<h2>Suggested</h2> <h2>Suggested</h2>
</div> </div>
<a href="index.html?source=https://therealfoxster.github.io/altsource/apps.json"> <a href="index.html?source=https://therealfoxster.github.io/altsource/apps.json">
<div class="suggestion"> <div class="suggestion">
<i class="bi bi-search"></i> <i class="bi bi-search"></i>
Foxster's AltSource Foxster's AltSource
</div> </div>
</a> </a>
<a href="index.html?source=https://qnblackcat.github.io/AltStore/apps.json"> <a href="index.html?source=https://qnblackcat.github.io/AltStore/apps.json">
<div class="suggestion"> <div class="suggestion">
<i class="bi bi-search"></i> <i class="bi bi-search"></i>
Qn_'s AltStore Repo Qn_'s AltStore Repo
</div> </div>
</a> </a>
<a href="index.html?source=https://alt.getutm.app"> <a href="index.html?source=https://alt.getutm.app">
<div class="suggestion"> <div class="suggestion">
<i class="bi bi-search"></i> <i class="bi bi-search"></i>
UTM Repository UTM Repository
</div> </div>
</a> </a>
<a href="index.html?source=https://flyinghead.github.io/flycast-builds/altstore.json"> <a href="index.html?source=https://flyinghead.github.io/flycast-builds/altstore.json">
<div class="suggestion"> <div class="suggestion">
<i class="bi bi-search"></i> <i class="bi bi-search"></i>
Flyinghead Flyinghead
</div> </div>
</a> </a>
<a href="index.html?source=https://provenance-emu.com/apps.json"> <a href="index.html?source=https://provenance-emu.com/apps.json">
<div class="suggestion"> <div class="suggestion">
<i class="bi bi-search"></i> <i class="bi bi-search"></i>
Provenance EMU Provenance EMU
</div> </div>
</a> </a>
<a href="https://github.com/therealFoxster/altsource-viewer" target="_blank"> <a href="https://github.com/therealFoxster/altsource-viewer" target="_blank">
<div class="suggestion"> <div class="suggestion">
<i class="bi bi-code-slash"></i> <i class="bi bi-code-slash"></i>
Source Code Source Code
</div> </div>
</a> </a>
</div> </div>
</div> </div>
<script src="js/shared.js"></script> <script src="js/shared.js"></script>
<script src="js/search.js"></script> <script src="js/search.js"></script>
</body> </body>
</html> </html>