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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

302
js/app.js
View File

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

View File

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

View File

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

View File

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

View File

@@ -1,19 +1,19 @@
(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 (urlSearchParams.has('source') && isValidHTTPURL(sourceURL))
success(sourceURL);
// If valid source provided
if (urlSearchParams.has('source') && isValidHTTPURL(sourceURL))
success(sourceURL);
const textField = document.querySelector("input");
textField.addEventListener("keypress", function (event) {
if (event.key === "Enter") {
event.preventDefault();
const textField = document.querySelector("input");
textField.addEventListener("keypress", function (event) {
if (event.key === "Enter") {
event.preventDefault();
const url = textField.value;
if (!isValidHTTPURL(url))
alert("Invalid HTTP URL.");
else success(url);
}
});
const url = textField.value;
if (!isValidHTTPURL(url))
alert("Invalid HTTP 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;
(function (global) {
var apps;
global.setApps = array =>
apps = array;
global.getAppWithBundleId = bundleId =>
apps?.find(app => app.bundleIdentifier == bundleId) ?? undefined;
var apps;
global.setApps = array =>
apps = array;
global.getAppWithBundleId = bundleId =>
apps?.find(app => app.bundleIdentifier == bundleId) ?? undefined;
setUpBackButton();
setUpBackButton();
})(this);
const newsItemHTML = (news, minimal = false) => `
<div class="news-item-wrapper"> ${news.url ?
"<a href='" + news.url + "'>" : ""}
<div class="item" style="background-color: #${news.tintColor};">
<div class="text">
<h3>${news.title}</h3>
<p>${news.caption}</p>
</div>${news.imageURL && !minimal ?
"<div class='image-wrapper'>" +
"<img src='" + news.imageURL + "'>" +
"</div>" : ""}
</div> ${news.url ?
"</a>" : ""} ${news.appID && !minimal ?
appHeaderHTML(getAppWithBundleId(news.appID)) ?? "" : ""}
"<a href='" + news.url + "'>" : ""}
<div class="item" style="background-color: #${news.tintColor};">
<div class="text">
<h3>${news.title}</h3>
<p>${news.caption}</p>
</div>${news.imageURL && !minimal ?
"<div class='image-wrapper'>" +
"<img src='" + news.imageURL + "'>" +
"</div>" : ""}
</div> ${news.url ?
"</a>" : ""} ${news.appID && !minimal ?
appHeaderHTML(getAppWithBundleId(news.appID)) ?? "" : ""}
</div>`;
const appHeaderHTML = app => app ? `
<div class="item">
<div class="app-header">
<div class="content">
<img src="${app.iconURL}" alt="">
<div class="right">
<div class="text">
<p class="title">${app.name}</p>
<p class="subtitle">${app.developerName}</p>
</div>
<a href="app.html?source=${sourceURL}&id=${app.bundleIdentifier}">
<button class="uibutton" style="background-color: #${app.tintColor};">View</button>
</a>
</div>
</div>
<div class="background" style="background-color: #${app.tintColor};"></div>
</div>
<div class="app-header">
<div class="content">
<img src="${app.iconURL}" alt="">
<div class="right">
<div class="text">
<p class="title">${app.name}</p>
<p class="subtitle">${app.developerName}</p>
</div>
<a href="app.html?source=${sourceURL}&id=${app.bundleIdentifier}">
<button class="uibutton" style="background-color: #${app.tintColor};">View</button>
</a>
</div>
</div>
<div class="background" style="background-color: #${app.tintColor};"></div>
</div>
</div>` : undefined;
function insertAddToAltStoreBanner() {
document.getElementById("top")?.insertAdjacentHTML("afterbegin", `
<div class="uibanner">
<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="text-container">
<p class="title-text">AltStore <span class="small beta badge"></span></p>
<p class="detail-text">
Add this source to AltStore to receive app updates (requires AltStore beta)
</p>
</div>
<a href="altstore://source?url=${sourceURL}">
<button>Add</button>
</a>
</div>
</div>`);
document.getElementById("top")?.insertAdjacentHTML("afterbegin", `
<div class="uibanner">
<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="text-container">
<p class="title-text">AltStore <span class="small beta badge"></span></p>
<p class="detail-text">
Add this source to AltStore to receive app updates (requires AltStore beta)
</p>
</div>
<a href="altstore://source?url=${sourceURL}">
<button>Add</button>
</a>
</div>
</div>`);
}
function insertNavigationBar(title) {
document.getElementById("top")?.insertAdjacentHTML("beforeend", `
<div id="nav-bar">
<button id="back" type="button">
<i class="bi bi-chevron-left"></i>
Back
</button>
<div id="title">
<p>${title ?? ""}</p>
</div>
<button id="back" class="hidden">
<i class="bi bi-chevron-left"></i>
Back
</button>
</div>`);
setUpBackButton();
document.getElementById("top")?.insertAdjacentHTML("beforeend", `
<div id="nav-bar">
<button id="back" type="button">
<i class="bi bi-chevron-left"></i>
Back
</button>
<div id="title">
<p>${title ?? ""}</p>
</div>
<button id="back" class="hidden">
<i class="bi bi-chevron-left"></i>
Back
</button>
</div>`);
setUpBackButton();
}
// https://stackoverflow.com/a/43467144/19227228
function isValidHTTPURL(string) {
var url;
try {
url = new URL(string);
} catch (error) {
console.error("An error occurred.", error);
return false;
}
return url.protocol == "http:" || url.protocol == "https:";
var url;
try {
url = new URL(string);
} catch (error) {
console.error("An error occurred.", error);
return false;
}
return url.protocol == "http:" || url.protocol == "https:";
}
function formatString(string) {
if (!string) return undefined;
if (!string) return undefined;
// URLs
const urlArray = string.match(urlRegex);
// const urlSet = [...new Set(urlArray)]; // Converting to set to remove duplicates
var result = "";
urlArray?.forEach(url => {
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)
let endIndexOfClosingTag = string.indexOf("</a>") + 4;
let formattedSubstring = string.substring(0, endIndexOfClosingTag);
result += formattedSubstring;
string = string.replace(formattedSubstring, "");
});
// URLs
const urlArray = string.match(urlRegex);
// const urlSet = [...new Set(urlArray)]; // Converting to set to remove duplicates
var result = "";
urlArray?.forEach(url => {
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)
let endIndexOfClosingTag = string.indexOf("</a>") + 4;
let formattedSubstring = string.substring(0, endIndexOfClosingTag);
result += formattedSubstring;
string = string.replace(formattedSubstring, "");
});
result += string;
result += string;
// New lines
return result.replaceAll("\n", "<br>");
// New lines
return result.replaceAll("\n", "<br>");
}
function setTintColor(color) {
document.querySelector(':root')?.style.setProperty("--accent-color", `#${color}`);
document.querySelector(':root')?.style.setProperty("--accent-color", `#${color}`);
}
function setUpBackButton() {
document.getElementById("back")?.addEventListener("click", () => history.back(1));
document.getElementById("back")?.addEventListener("click", () => history.back(1));
}
function search() {
window.location.replace("search.html");
window.location.replace("search.html");
}
const $ = selector => selector.startsWith("#") && !selector.includes(".") && !selector.includes(" ")
? document.getElementById(selector.substring(1))
: document.querySelectorAll(selector);
? document.getElementById(selector.substring(1))
: document.querySelectorAll(selector);

View File

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

View File

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