Compare commits

..

10 Commits

27 changed files with 1784 additions and 1318 deletions

View File

@ -1,10 +1,44 @@
<!doctype html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + Preact</title>
<meta
name="description"
content="Fakebook social media app, which reminds you Facebook and contains AI generated code to use AINIRO Magic backend"
/>
<title>fakebook-aigen</title>
<!-- Start Single Page Apps for GitHub Pages -->
<script type="text/javascript">
// Single Page Apps for GitHub Pages
// MIT License
// https://github.com/rafgraph/spa-github-pages
// This script checks to see if a redirect is present in the query string,
// converts it back into the correct url and adds it to the
// browser's history using window.history.replaceState(...),
// which won't cause the browser to attempt to load the new url.
// When the single page app is loaded further down in this file,
// the correct url will be waiting in the browser's history for
// the single page app to route accordingly.
(function (l) {
if (l.search[1] === "/") {
var decoded = l.search
.slice(1)
.split("&")
.map(function (s) {
return s.replace(/~and~/g, "&");
})
.join("?");
window.history.replaceState(
null,
null,
l.pathname.slice(0, -1) + decoded + l.hash
);
}
})(window.location);
</script>
<!-- End Single Page Apps for GitHub Pages -->
</head>
<body>
<div id="app"></div>

616
package-lock.json generated
View File

@ -1,12 +1,12 @@
{
"name": "fakebook-ainiro",
"version": "0.0.0",
"version": "0.1.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "fakebook-ainiro",
"version": "0.0.0",
"version": "0.1.0",
"dependencies": {
"@microsoft/signalr": "^8.0.7",
"@reduxjs/toolkit": "^1.8.3",
@ -17,11 +17,11 @@
"react-icons": "^4.2.0",
"react-player": "^2.12.0",
"react-redux": "^8.0.2",
"react-router-dom": "^5.2.0",
"signalr": "^2.4.3"
"react-router-dom": "^5.2.0"
},
"devDependencies": {
"@preact/preset-vite": "^2.9.3",
"gh-pages": "^6.3.0",
"vite": "^6.0.5"
}
},
@ -847,6 +847,44 @@
"ws": "^7.4.5"
}
},
"node_modules/@nodelib/fs.scandir": {
"version": "2.1.5",
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
"integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
"dev": true,
"license": "MIT",
"dependencies": {
"@nodelib/fs.stat": "2.0.5",
"run-parallel": "^1.1.9"
},
"engines": {
"node": ">= 8"
}
},
"node_modules/@nodelib/fs.stat": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
"integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 8"
}
},
"node_modules/@nodelib/fs.walk": {
"version": "1.2.8",
"resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
"integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@nodelib/fs.scandir": "2.1.5",
"fastq": "^1.6.0"
},
"engines": {
"node": ">= 8"
}
},
"node_modules/@popperjs/core": {
"version": "2.11.8",
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz",
@ -1333,6 +1371,23 @@
"node": ">=6.5"
}
},
"node_modules/array-union": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
"integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=8"
}
},
"node_modules/async": {
"version": "3.2.6",
"resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz",
"integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==",
"dev": true,
"license": "MIT"
},
"node_modules/babel-plugin-transform-hook-names": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/babel-plugin-transform-hook-names/-/babel-plugin-transform-hook-names-1.0.2.tgz",
@ -1370,6 +1425,19 @@
"popper.js": "^1.16.1"
}
},
"node_modules/braces": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
"integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
"dev": true,
"license": "MIT",
"dependencies": {
"fill-range": "^7.1.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/browserslist": {
"version": "4.24.4",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.4.tgz",
@ -1430,6 +1498,23 @@
"integrity": "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==",
"license": "MIT"
},
"node_modules/commander": {
"version": "13.1.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-13.1.0.tgz",
"integrity": "sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=18"
}
},
"node_modules/commondir": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz",
"integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==",
"dev": true,
"license": "MIT"
},
"node_modules/convert-source-map": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
@ -1509,6 +1594,19 @@
"node": ">=6"
}
},
"node_modules/dir-glob": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
"integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==",
"dev": true,
"license": "MIT",
"dependencies": {
"path-type": "^4.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/dom-helpers": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz",
@ -1585,6 +1683,13 @@
"dev": true,
"license": "ISC"
},
"node_modules/email-addresses": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/email-addresses/-/email-addresses-5.0.0.tgz",
"integrity": "sha512-4OIPYlA6JXqtVn8zpHpGiI7vE6EQOAg16aGnDMIAlZVinnoZ8208tW1hAbjWydgN/4PLTT9q+O1K6AH/vALJGw==",
"dev": true,
"license": "MIT"
},
"node_modules/entities": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
@ -1649,6 +1754,16 @@
"node": ">=6"
}
},
"node_modules/escape-string-regexp": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
"integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=0.8.0"
}
},
"node_modules/estree-walker": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
@ -1674,6 +1789,33 @@
"node": ">=12.0.0"
}
},
"node_modules/fast-glob": {
"version": "3.3.3",
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz",
"integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@nodelib/fs.stat": "^2.0.2",
"@nodelib/fs.walk": "^1.2.3",
"glob-parent": "^5.1.2",
"merge2": "^1.3.0",
"micromatch": "^4.0.8"
},
"engines": {
"node": ">=8.6.0"
}
},
"node_modules/fastq": {
"version": "1.19.1",
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz",
"integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==",
"dev": true,
"license": "ISC",
"dependencies": {
"reusify": "^1.0.4"
}
},
"node_modules/fetch-cookie": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/fetch-cookie/-/fetch-cookie-2.2.0.tgz",
@ -1684,6 +1826,104 @@
"tough-cookie": "^4.0.0"
}
},
"node_modules/filename-reserved-regex": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz",
"integrity": "sha512-lc1bnsSr4L4Bdif8Xb/qrtokGbq5zlsms/CYH8PP+WtCkGNF65DPiQY8vG3SakEdRn8Dlnm+gW/qWKKjS5sZzQ==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=4"
}
},
"node_modules/filenamify": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/filenamify/-/filenamify-4.3.0.tgz",
"integrity": "sha512-hcFKyUG57yWGAzu1CMt/dPzYZuv+jAJUT85bL8mrXvNe6hWj6yEHEc4EdcgiA6Z3oi1/9wXJdZPXF2dZNgwgOg==",
"dev": true,
"license": "MIT",
"dependencies": {
"filename-reserved-regex": "^2.0.0",
"strip-outer": "^1.0.1",
"trim-repeated": "^1.0.0"
},
"engines": {
"node": ">=8"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/fill-range": {
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
"integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
"dev": true,
"license": "MIT",
"dependencies": {
"to-regex-range": "^5.0.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/find-cache-dir": {
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz",
"integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==",
"dev": true,
"license": "MIT",
"dependencies": {
"commondir": "^1.0.1",
"make-dir": "^3.0.2",
"pkg-dir": "^4.1.0"
},
"engines": {
"node": ">=8"
},
"funding": {
"url": "https://github.com/avajs/find-cache-dir?sponsor=1"
}
},
"node_modules/find-up": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
"integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
"dev": true,
"license": "MIT",
"dependencies": {
"locate-path": "^5.0.0",
"path-exists": "^4.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/fs-extra": {
"version": "11.3.0",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.0.tgz",
"integrity": "sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew==",
"dev": true,
"license": "MIT",
"dependencies": {
"graceful-fs": "^4.2.0",
"jsonfile": "^6.0.1",
"universalify": "^2.0.0"
},
"engines": {
"node": ">=14.14"
}
},
"node_modules/fs-extra/node_modules/universalify": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz",
"integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 10.0.0"
}
},
"node_modules/fsevents": {
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
@ -1709,6 +1949,42 @@
"node": ">=6.9.0"
}
},
"node_modules/gh-pages": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/gh-pages/-/gh-pages-6.3.0.tgz",
"integrity": "sha512-Ot5lU6jK0Eb+sszG8pciXdjMXdBJ5wODvgjR+imihTqsUWF2K6dJ9HST55lgqcs8wWcw6o6wAsUzfcYRhJPXbA==",
"dev": true,
"license": "MIT",
"dependencies": {
"async": "^3.2.4",
"commander": "^13.0.0",
"email-addresses": "^5.0.0",
"filenamify": "^4.3.0",
"find-cache-dir": "^3.3.1",
"fs-extra": "^11.1.1",
"globby": "^11.1.0"
},
"bin": {
"gh-pages": "bin/gh-pages.js",
"gh-pages-clean": "bin/gh-pages-clean.js"
},
"engines": {
"node": ">=10"
}
},
"node_modules/glob-parent": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
"dev": true,
"license": "ISC",
"dependencies": {
"is-glob": "^4.0.1"
},
"engines": {
"node": ">= 6"
}
},
"node_modules/globals": {
"version": "11.12.0",
"resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
@ -1719,6 +1995,34 @@
"node": ">=4"
}
},
"node_modules/globby": {
"version": "11.1.0",
"resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz",
"integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==",
"dev": true,
"license": "MIT",
"dependencies": {
"array-union": "^2.1.0",
"dir-glob": "^3.0.1",
"fast-glob": "^3.2.9",
"ignore": "^5.2.0",
"merge2": "^1.4.1",
"slash": "^3.0.0"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/graceful-fs": {
"version": "4.2.11",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
"integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
"dev": true,
"license": "ISC"
},
"node_modules/he": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
@ -1752,6 +2056,16 @@
"react-is": "^16.7.0"
}
},
"node_modules/ignore": {
"version": "5.3.2",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
"integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 4"
}
},
"node_modules/immer": {
"version": "9.0.21",
"resolved": "https://registry.npmjs.org/immer/-/immer-9.0.21.tgz",
@ -1771,6 +2085,39 @@
"loose-envify": "^1.0.0"
}
},
"node_modules/is-extglob": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
"integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/is-glob": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
"integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
"dev": true,
"license": "MIT",
"dependencies": {
"is-extglob": "^2.1.1"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/is-number": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=0.12.0"
}
},
"node_modules/isarray": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
@ -1781,7 +2128,8 @@
"version": "3.7.1",
"resolved": "https://registry.npmjs.org/jquery/-/jquery-3.7.1.tgz",
"integrity": "sha512-m4avr8yL8kmFN8psrbFFFmB/If14iN5o9nw/NgnnM+kybDJpRsAynV2BsfpTYrTRysYUdADVD7CkUUizgkpLfg==",
"license": "MIT"
"license": "MIT",
"peer": true
},
"node_modules/js-tokens": {
"version": "4.0.0",
@ -1815,6 +2163,29 @@
"node": ">=6"
}
},
"node_modules/jsonfile": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
"integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"universalify": "^2.0.0"
},
"optionalDependencies": {
"graceful-fs": "^4.1.6"
}
},
"node_modules/jsonfile/node_modules/universalify": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz",
"integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 10.0.0"
}
},
"node_modules/kolorist": {
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/kolorist/-/kolorist-1.8.0.tgz",
@ -1828,6 +2199,19 @@
"integrity": "sha512-kPEjMFtZvwL9TaZo0uZ2ml+Ye9HUMmPwbYRJ324qF9tqMejwykJ5ggTyvzmrbBeapCAbk98BSbTeovHEEP1uCA==",
"license": "MIT"
},
"node_modules/locate-path": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
"integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
"dev": true,
"license": "MIT",
"dependencies": {
"p-locate": "^4.1.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/loose-envify": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
@ -1863,12 +2247,52 @@
"node": ">=12"
}
},
"node_modules/make-dir": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
"integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
"dev": true,
"license": "MIT",
"dependencies": {
"semver": "^6.0.0"
},
"engines": {
"node": ">=8"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/memoize-one": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz",
"integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==",
"license": "MIT"
},
"node_modules/merge2": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
"integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 8"
}
},
"node_modules/micromatch": {
"version": "4.0.8",
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
"integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
"dev": true,
"license": "MIT",
"dependencies": {
"braces": "^3.0.3",
"picomatch": "^2.3.1"
},
"engines": {
"node": ">=8.6"
}
},
"node_modules/ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
@ -1955,6 +2379,55 @@
"node": ">=0.10.0"
}
},
"node_modules/p-limit": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
"integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
"dev": true,
"license": "MIT",
"dependencies": {
"p-try": "^2.0.0"
},
"engines": {
"node": ">=6"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/p-locate": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
"integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
"dev": true,
"license": "MIT",
"dependencies": {
"p-limit": "^2.2.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/p-try": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
"integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=6"
}
},
"node_modules/path-exists": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
"integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=8"
}
},
"node_modules/path-to-regexp": {
"version": "1.9.0",
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.9.0.tgz",
@ -1964,6 +2437,16 @@
"isarray": "0.0.1"
}
},
"node_modules/path-type": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
"integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=8"
}
},
"node_modules/picocolors": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
@ -1984,6 +2467,19 @@
"url": "https://github.com/sponsors/jonschlinkert"
}
},
"node_modules/pkg-dir": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz",
"integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"find-up": "^4.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/popper.js": {
"version": "1.16.1",
"resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1.tgz",
@ -2086,6 +2582,27 @@
"integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==",
"license": "MIT"
},
"node_modules/queue-microtask": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
"integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
"dev": true,
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
],
"license": "MIT"
},
"node_modules/react": {
"version": "17.0.2",
"resolved": "https://registry.npmjs.org/react/-/react-17.0.2.tgz",
@ -2347,6 +2864,17 @@
"integrity": "sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng==",
"license": "MIT"
},
"node_modules/reusify": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz",
"integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==",
"dev": true,
"license": "MIT",
"engines": {
"iojs": ">=1.0.0",
"node": ">=0.10.0"
}
},
"node_modules/rollup": {
"version": "4.30.1",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.30.1.tgz",
@ -2386,6 +2914,30 @@
"fsevents": "~2.3.2"
}
},
"node_modules/run-parallel": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
"integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
"dev": true,
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
],
"license": "MIT",
"dependencies": {
"queue-microtask": "^1.2.2"
}
},
"node_modules/scheduler": {
"version": "0.20.2",
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.20.2.tgz",
@ -2412,13 +2964,14 @@
"integrity": "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==",
"license": "MIT"
},
"node_modules/signalr": {
"version": "2.4.3",
"resolved": "https://registry.npmjs.org/signalr/-/signalr-2.4.3.tgz",
"integrity": "sha512-RbBKFVCZvDgyyxZDeu6Yck9T+diZO07GB0bDiKondUhBY1H8JRQSOq8R0pLkf47ddllQAssYlp7ckQAeom24mw==",
"license": "Apache-2.0",
"dependencies": {
"jquery": ">=1.6.4"
"node_modules/slash": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
"integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=8"
}
},
"node_modules/source-map": {
@ -2451,6 +3004,19 @@
"node": ">=16"
}
},
"node_modules/strip-outer": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/strip-outer/-/strip-outer-1.0.1.tgz",
"integrity": "sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg==",
"dev": true,
"license": "MIT",
"dependencies": {
"escape-string-regexp": "^1.0.2"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/tiny-invariant": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz",
@ -2463,6 +3029,19 @@
"integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==",
"license": "MIT"
},
"node_modules/to-regex-range": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"is-number": "^7.0.0"
},
"engines": {
"node": ">=8.0"
}
},
"node_modules/tough-cookie": {
"version": "4.1.4",
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz",
@ -2484,6 +3063,19 @@
"integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==",
"license": "MIT"
},
"node_modules/trim-repeated": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz",
"integrity": "sha512-pkonvlKk8/ZuR0D5tLW8ljt5I8kmxp2XKymhepUeOdCEfKpZaktSArkLHZt76OB1ZvO9bssUsDty4SWhLvZpLg==",
"dev": true,
"license": "MIT",
"dependencies": {
"escape-string-regexp": "^1.0.2"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/uncontrollable": {
"version": "7.2.1",
"resolved": "https://registry.npmjs.org/uncontrollable/-/uncontrollable-7.2.1.tgz",

View File

@ -1,12 +1,15 @@
{
"name": "fakebook-ainiro",
"private": true,
"version": "0.0.0",
"version": "0.1.0",
"homepage": "https://alexerdei73.github.io/fakebook-aigen",
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview"
"preview": "vite preview",
"predeploy": "npm run build",
"deploy": "gh-pages -d dist"
},
"dependencies": {
"@microsoft/signalr": "^8.0.7",
@ -18,11 +21,11 @@
"react-icons": "^4.2.0",
"react-player": "^2.12.0",
"react-redux": "^8.0.2",
"react-router-dom": "^5.2.0",
"signalr": "^2.4.3"
"react-router-dom": "^5.2.0"
},
"devDependencies": {
"@preact/preset-vite": "^2.9.3",
"gh-pages": "^6.3.0",
"vite": "^6.0.5"
}
}

19
prompts/commit30.txt Normal file
View File

@ -0,0 +1,19 @@
Do you still remember exactly the backend.js file?
Now I want you to clean it up a bit.
1.I only want to see one line comments
2.You only read the local storage in one function, which
updates the global variables you use for the (current) user
id and the token for the authorization of the requests
3.Let's keep everything working just unify the code style
a bit for better readability
Thank you
Can I get the whole file?
The rest of the code please?
You forgot to provide the password reminder function for the
signatures.

6
prompts/commit32.txt Normal file
View File

@ -0,0 +1,6 @@
We are going to make another feature, which is the password
reminder email. We need to write the function, which will send a
request to the GET pswreminder endpoint. It has only one
parameter, which is the email. The user gets the email with a
link, which is valid for an hour and takes them to a site to
change the password.

10
prompts/commit34.txt Normal file
View File

@ -0,0 +1,10 @@
The last fix before deployment is the online status, when someone
closes the browser window, without signing out. Although we
handle the event which is visibility change to send the request,
the browser closes before the request is sent. Fix this in the
backend.js file and remove the unnecessary before unload listener
from the UserAccount component.
How about if someone just hides the browser window on mobile for
example?

13
prompts/commit36.txt Normal file
View File

@ -0,0 +1,13 @@
Audio description:
"How can I deploy my previous project on GitHub pages? Take into
account that it's a single page application and GitHub pages is
not the best for deploying these or you need to use some kind of
tool for React apps. Let me the detailed answer, please."
What are the differences for Vite build?
// The deployment worked at this point, but the AI (o3) eliminated
// the usage of the isFriendsListPage field from the accountPage
// slice in the Redux store. This field determines in the UI if it
// shows the Profile component or the FriendsListPage component.
// I manually debugged the UserAccount component.

50
public/404.html Normal file
View File

@ -0,0 +1,50 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>fakebook-aigen</title>
<script type="text/javascript">
// Single Page Apps for GitHub Pages
// MIT License
// https://github.com/rafgraph/spa-github-pages
// This script takes the current url and converts the path and query
// string into just a query string, and then redirects the browser
// to the new url with only a query string and hash fragment,
// e.g. https://www.foo.tld/one/two?a=b&c=d#qwe, becomes
// https://www.foo.tld/?/one/two&a=b~and~c=d#qwe
// Note: this 404.html file must be at least 512 bytes for it to work
// with Internet Explorer (it is currently > 512 bytes)
// If you're creating a Project Pages site and NOT using a custom domain,
// then set pathSegmentsToKeep to 1 (enterprise users may need to set it to > 1).
// This way the code will only replace the route part of the path, and not
// the real directory in which the app resides, for example:
// https://username.github.io/repo-name/one/two?a=b&c=d#qwe becomes
// https://username.github.io/repo-name/?/one/two&a=b~and~c=d#qwe
// Otherwise, leave pathSegmentsToKeep as 0.
var pathSegmentsToKeep = 1;
var l = window.location;
l.replace(
l.protocol +
"//" +
l.hostname +
(l.port ? ":" + l.port : "") +
l.pathname
.split("/")
.slice(0, 1 + pathSegmentsToKeep)
.join("/") +
"/?/" +
l.pathname
.slice(1)
.split("/")
.slice(pathSegmentsToKeep)
.join("/")
.replace(/&/g, "~and~") +
(l.search ? "&" + l.search.slice(1).replace(/&/g, "~and~") : "") +
l.hash
);
</script>
</head>
<body></body>
</html>

View File

@ -43,10 +43,12 @@ function App() {
const firstName = name.join(" ");
const profileLink = `/fakebook/${lastName}.${firstName}`;
const profileLink = `/${lastName}.${firstName}`;
useEffect(() => dispatch(profileLinkSet(profileLink)), [profileLink, dispatch]);
useEffect(
() => dispatch(profileLinkSet(profileLink)),
[profileLink, dispatch]
);
//handling the password reminder button
const [isModalSignup, setModalSignup] = useState(true);
@ -65,15 +67,16 @@ function App() {
else return <></>;
} else {
return (
<Col className="bg-200 vh-100">
<Row className="h-100 align-items-center">
<Col className='bg-200 vh-100'>
<Row className='h-100 align-items-center'>
<Col
lg={{ span: 5, offset: 1 }}
className="d-flex justify-content-center">
className='d-flex justify-content-center'
>
<RecentLogins />
</Col>
<Col lg={5} className="bg-200 d-flex justify-content-center">
<div className="login p-3 bg-light">
<Col lg={5} className='bg-200 d-flex justify-content-center'>
<div className='login p-3 bg-light'>
<Login
onClickForgottenPswd={handleClickPasswordReminderBtn}
></Login>
@ -81,10 +84,11 @@ function App() {
<hr />
<Button
variant="success"
size="lg"
className="d-block w-60 mx-auto mt-4"
onClick={handleShow}>
variant='success'
size='lg'
className='d-block w-60 mx-auto mt-4'
onClick={handleShow}
>
<b>Create New Account</b>
</Button>
</div>
@ -93,7 +97,8 @@ function App() {
<SignupModal
show={show && isModalSignup}
onHide={handleCloseCallback}
onExit={() => setModalSignup(true)}></SignupModal>
onExit={() => setModalSignup(true)}
></SignupModal>
<PasswordReminderModal
show={show && !isModalSignup}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,25 @@
import React from "react";
// For Bootstrap 4: use "sr-only" for visually hidden text
const CustomToggle = React.forwardRef(({ onClick }, ref) => (
<button
ref={ref}
className='btn dropdown-toggle custom-drop-down-btn'
aria-label='Account menu'
data-toggle='dropdown'
aria-haspopup='true'
aria-expanded='false'
type='button'
onClick={(e) => {
e.preventDefault();
onClick(e);
}}
>
<span className='sr-only'>Account menu</span>
{/* Bootstrap's caret will appear via .dropdown-toggle CSS */}
</button>
));
export default CustomToggle;

View File

@ -17,50 +17,50 @@ const FriendCard = (props) => {
function handleClick() {
history.push(
user.index && user.index > 0
? `/fakebook/${user.lastname}.${user.firstname}.${user.index}`
: `/fakebook/${user.lastname}.${user.firstname}`
? `/${user.lastname}.${user.firstname}.${user.index}`
: `/${user.lastname}.${user.firstname}`
);
}
return (
<Col xs={6} className="my-3">
<Col xs={6} className='my-3'>
<OverlayTrigger
placement="auto"
placement='auto'
show={showOverlay}
overlay={
<div
className="popup-card"
className='popup-card'
onMouseEnter={() => setShowOverlay(true)}
onMouseLeave={() => setShowOverlay(false)}
onClick={handleClick}
>
<div className="m-3">
<CircularImage size="120" url={user.profilePictureURL} />
<div className='m-3'>
<CircularImage size='120' url={user.profilePictureURL} />
</div>
<h4 className="name-tag">
<h4 className='name-tag'>
<b>{userName}</b>
</h4>
</div>
}
>
<button
type="button"
type='button'
onClick={handleClick}
className="friend-btn"
tabIndex="-1"
className='friend-btn'
tabIndex='-1'
>
<StorageImage
storagePath={user.profilePictureURL}
width="90px"
height="90px"
alt=""
className="profile-picture"
width='90px'
height='90px'
alt=''
className='profile-picture'
onMouseEnter={() => setShowOverlay(true)}
onMouseLeave={() => setShowOverlay(false)}
/>
</button>
</OverlayTrigger>
<button type="button" className="ml-3 friend-btn" onClick={handleClick}>
<button type='button' className='ml-3 friend-btn' onClick={handleClick}>
<b>{userName}</b>
</button>
</Col>

View File

@ -16,10 +16,10 @@ const FriendList = (props) => {
const isModal = variant === "modal";
return (
<Col xs="auto" className="overflow-auto mh-100">
<div id="col-1" className="m-2">
<Col xs='auto' className='overflow-auto mh-100'>
<div id='col-1' className='m-2'>
{usersToUse.map((user, index) => {
let profileLink = `/fakebook/${user.lastname}.${user.firstname}`;
let profileLink = `/${user.lastname}.${user.firstname}`;
if (user.index && user.index > 0)
profileLink = profileLink + `.${user.index}`;
return (
@ -30,10 +30,10 @@ const FriendList = (props) => {
>
<ProfileLink
user={user}
fullname="true"
fullname='true'
size={isModal ? "40" : "60"}
bold="true"
className="pb-1"
bold='true'
className='pb-1'
/>
</Link>
);

View File

@ -8,9 +8,8 @@ import imgFriends from "../images/friends.jpg";
import { useDispatch } from "react-redux";
import { linkUpdated } from "../features/link/linkSlice";
const FriendsListPage = (props) => {
const FRIENDS_LIST_PAGE_PATH = "/fakebook/friends/list";
const FriendsListPage = () => {
const FRIENDS_LIST_PAGE_PATH = "/friends/list";
const location = useLocation();
const dispatch = useDispatch();
@ -23,23 +22,23 @@ const FriendsListPage = (props) => {
}, [dispatch]);
return window.innerWidth > 600 || isNoUser ? (
<Row className="overflow-hidden friends-list">
<Row className='overflow-hidden friends-list'>
<FriendList />
<Col className="overflow-auto mh-100 hide-scrollbar col-two">
<Col className='overflow-auto mh-100 hide-scrollbar col-two'>
{isNoUser ? (
<div className="h-100 w-100 d-flex flex-column align-items-center justify-content-center">
<div className='h-100 w-100 d-flex flex-column align-items-center justify-content-center'>
<img
width="200px"
width='200px'
src={imgFriends}
alt="cartoon of fakebook friends"
className="p-4"
alt='cartoon of fakebook friends'
className='p-4'
/>
<h5 className="text-muted">
<h5 className='text-muted'>
<b>Select people's names to preview their profile.</b>
</h5>
</div>
) : (
<div className="profile-container">
<div className='profile-container'>
<Profile />
</div>
)}

View File

@ -11,26 +11,26 @@ const LeftNavbar = (props) => {
const user = useSelector((state) => state.currentUser);
return (
<Nav className="flex-column mt-3" id="left-navbar">
<div className="navitem">
<Nav className='flex-column mt-3' id='left-navbar'>
<div className='navitem'>
<Nav.Link
as={Link}
to={props.profileLink}
className="text-dark flex-column justify-content-center"
className='text-dark flex-column justify-content-center'
>
<ProfileLink user={user} size="26" fullname="true" />
<ProfileLink user={user} size='26' fullname='true' />
</Nav.Link>
</div>
<div className="navitem">
<Nav.Link as={Link} to="/fakebook/friends/list" className="text-dark">
<FaUserFriends size="26px" className="text-info mr-2" />
<div className="d-inline">Friends</div>
<div className='navitem'>
<Nav.Link as={Link} to='/friends/list' className='text-dark'>
<FaUserFriends size='26px' className='text-info mr-2' />
<div className='d-inline'>Friends</div>
</Nav.Link>
</div>
<div className="navitem">
<Nav.Link as={Link} to="/fakebook/watch" className="text-dark">
<MdOndemandVideo size="26px" className="text-info mr-2" />
<div className="d-inline">Watch</div>
<div className='navitem'>
<Nav.Link as={Link} to='/watch' className='text-dark'>
<MdOndemandVideo size='26px' className='text-info mr-2' />
<div className='d-inline'>Watch</div>
</Nav.Link>
</div>
</Nav>

View File

@ -16,8 +16,8 @@ const MiniFriends = (props) => {
const friendsLink =
user.index && user.index > 0
? `/fakebook/${user.lastname}.${user.firstname}.${user.index}/Friends`
: `/fakebook/${user.lastname}.${user.firstname}/Friends`;
? `/${user.lastname}.${user.firstname}.${user.index}/Friends`
: `/${user.lastname}.${user.firstname}/Friends`;
function handleClick() {
handleClickLink(
@ -33,19 +33,19 @@ const MiniFriends = (props) => {
<Card {...rest}>
<Card.Body>
<Card.Title>
<Link to={friendsLink} className="text-body" onClick={handleClick}>
<Link to={friendsLink} className='text-body' onClick={handleClick}>
<b>Friends</b>
</Link>
</Card.Title>
<Card.Subtitle className="text-muted">
<Card.Subtitle className='text-muted'>
{users.length} friends
</Card.Subtitle>
<Row>
{users.map((user, index) => {
const userProfileURL =
user.index && user.index > 0
? `/fakebook/${user.lastname}.${user.firstname}.${user.index}`
: `/fakebook/${user.lastname}.${user.firstname}`;
? `/${user.lastname}.${user.firstname}.${user.index}`
: `/${user.lastname}.${user.firstname}`;
const userName = `${user.firstname} ${user.lastname}`;
return (
//we render maximum 9 friends
@ -53,24 +53,26 @@ const MiniFriends = (props) => {
<Col
key={index}
xs={4}
className="m-0"
className='m-0'
style={{
paddingLeft: "3px",
paddingRight: "3px",
paddingTop: "0",
paddingBottom: "3px",
}}>
}}
>
<ResponsiveImage
photo={user.profilePictureURL}
width="100%"
height="100%"
useStoragePath="true"
width='100%'
height='100%'
useStoragePath='true'
/>
<Link
to={userProfileURL}
className="text-body"
onClick={handleClick}>
<div className="w-100" style={{ height: "2.5em" }}>
className='text-body'
onClick={handleClick}
>
<div className='w-100' style={{ height: "2.5em" }}>
<p style={{ fontSize: "0.9em" }}>
<b>{userName}</b>
</p>

View File

@ -22,7 +22,7 @@ const MiniPhotos = (props) => {
const userSlug =
user.index && user.index > 0 ? `${slugBase}.${user.index}` : slugBase;
const photosLink = `/fakebook/${userSlug}/Photos`;
const photosLink = `/${userSlug}/Photos`;
/* ---------------------------------------------------------------- */
@ -59,7 +59,7 @@ const MiniPhotos = (props) => {
}}
>
<Link
to={`/fakebook/photo/${userID}/${index}`}
to={`/photo/${userID}/${index}`}
className='text-body'
onClick={handleClick}
tabIndex='-1'

View File

@ -23,21 +23,21 @@ const PhotoViewer = () => {
}, [location]);
const handleSelect = (selectedIndex, e) => {
history.push(`/fakebook/photo/${userID}/${selectedIndex}`);
history.push(`/photo/${userID}/${selectedIndex}`);
};
return (
<Row
className="bg-200"
className='bg-200'
style={{
position: "relative",
top: "50px",
height: "89vh",
}}
>
<Col md={9} className="h-100" style={{ backgroundColor: "black" }}>
<Col md={9} className='h-100' style={{ backgroundColor: "black" }}>
<Carousel
className="w-100 h-100"
className='w-100 h-100'
interval={null}
indicators={false}
activeIndex={activeIndex}
@ -54,7 +54,7 @@ const PhotoViewer = () => {
>
<StorageImage
storagePath={`/${userID}/${photo.fileName}`}
alt=""
alt=''
style={{
position: "absolute",
top: "50%",

View File

@ -28,15 +28,15 @@ const Photos = (props) => {
}, [activeLink, photosLinkRef, setActiveLink]);
return (
<Card variant="light" className="w-100">
<Card variant='light' className='w-100'>
<Card.Body>
<Card.Title>
<Link to={url} className="text-body">
<Link to={url} className='text-body'>
<b>Photos</b>
</Link>
{isCurrentUser && (
<Button
variant="link"
variant='link'
style={{
textDecoration: "none",
float: "right",
@ -47,14 +47,14 @@ const Photos = (props) => {
</Button>
)}
</Card.Title>
<Row className="w-100">
<Row className='w-100'>
{photos.map((photo, index) => {
return (
<Col key={index} xs={6} sm={4} md={3} lg={2} className="p-1">
<Link to={`/fakebook/photo/${userID}/${index}`}>
<Col key={index} xs={6} sm={4} md={3} lg={2} className='p-1'>
<Link to={`/photo/${userID}/${index}`}>
<ResponsiveImage
width="100%"
height="100%"
width='100%'
height='100%'
userID={userID}
photo={photo}
index={index}

View File

@ -51,13 +51,17 @@
width: 100%;
border: 2px solid lightgray;
border-radius: 10px;
padding: 10px;
overflow: hidden;
background: #000;
position: relative;
padding-bottom: 56.25%; /* 16:9, for an aspect ratio of 1:1 change to this value to 100% */
padding-bottom: 56.25%;
height: 0;
}
.react-player {
position: absolute;
top: 0;
left: 0;
width: 100% !important;
height: 100% !important;
}

View File

@ -133,80 +133,84 @@ const PostModal = (props) => {
<>
<Modal show={show} onHide={onClose}>
<Modal.Header closeButton>
<div className="w-100 d-flex justify-content-center">
<div className='w-100 d-flex justify-content-center'>
<Modal.Title>
<b>Create Post</b>
</Modal.Title>
</div>
</Modal.Header>
<Modal.Body>
<ProfileLink user={user} size="45" fullname="true" bold="true" />
<div className="mt-2 scrolling-container">
<ProfileLink user={user} size='45' fullname='true' bold='true' />
<div className='mt-2 scrolling-container'>
<textarea
type="text"
type='text'
onChange={handleChange}
className="w-100 mt-2 textarea"
className='w-100 mt-2 textarea'
placeholder={getPlaceholder()}
rows={getRows()}
value={post.text}></textarea>
value={post.text}
></textarea>
{post.isPhoto && (
<div className="mb-2 img-container">
<div className='mb-2 img-container'>
<StorageImage
alt=""
alt=''
storagePath={`/${post.photoURL}`}
className="w-100 img-to-post"
className='w-100 img-to-post'
/>
<div className="close-btn-container">
<div className='close-btn-container'>
<CloseButton onClick={deletePhoto} />
</div>
</div>
)}
{post.isYoutube && (
<div className="mb-2 video-container">
<div className='mb-2 video-container'>
<iframe
src={post.youtubeURL}
title="YouTube video player"
frameBorder="0"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope"
allowFullScreen></iframe>
<div className="close-btn-container">
title='YouTube video player'
allow='accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope'
allowFullScreen
></iframe>
<div className='close-btn-container'>
<CloseButton onClick={deleteYoutubeVideo} />
</div>
</div>
)}
</div>
<div className="w-100 my-2 add-to-post">
<div className='w-100 my-2 add-to-post'>
<b>Add to your post</b>
<Button
className="ml-2 add-photo-btn"
variant="light"
size="sm"
className='ml-2 add-photo-btn'
variant='light'
size='sm'
onClick={addYoutubeVideo}
disabled={post.isPhoto || post.isYoutube}>
disabled={post.isPhoto || post.isYoutube}
>
<AiFillYoutube
size="26px"
className="text-danger"
aria-label="YouTube"
size='26px'
className='text-danger'
aria-label='YouTube'
/>
</Button>
<Button
className="ml-2 add-photo-btn"
variant="light"
size="sm"
className='ml-2 add-photo-btn'
variant='light'
size='sm'
onClick={() => setShowUploadPhotoDlg(true)}
disabled={post.isPhoto || post.isYoutube}>
disabled={post.isPhoto || post.isYoutube}
>
<HiOutlinePhotograph
size="26px"
className="text-success"
aria-label="photo"
size='26px'
className='text-success'
aria-label='photo'
/>
</Button>
</div>
<Button
variant={variant}
className="w-100 mt-3"
className='w-100 mt-3'
disabled={disabled}
onClick={uploadPost}>
onClick={uploadPost}
>
<b>Post</b>
</Button>
</Modal.Body>

View File

@ -18,14 +18,14 @@ const ProfileLink = (props) => {
color: "inherited",
}}
>
<Col xs="auto" className="px-2 ml-2">
<Col xs='auto' className='px-2 ml-2'>
<CircularImage
size={size}
url={profilePictureURL}
isOnline={isOnline}
/>
</Col>
<Col className="align-self-center p-0" style={{ color: "inherited" }}>
<Col className='align-self-center p-0 text-dark'>
{bold === "true" ? <b>{name}</b> : name}
</Col>
</Row>

View File

@ -16,10 +16,10 @@ const SelectBgPhotoModal = (props) => {
{photos.map((photo, index) => {
return (
<StorageImage
className="m-1"
width="31%"
height="90px"
alt=""
className='m-1'
width='31%'
height='90px'
alt=''
key={index}
id={index}
storagePath={`/${userID}/${photo.fileName}`}

View File

@ -45,6 +45,37 @@
left: 0;
}
.custom-drop-down-btn .dropdown-toggle {
display: flex;
align-items: center;
justify-content: center;
width: 1.7em; /* as in your original custom-drop-down-btn styling */
height: 1.7em;
padding: 0 !important; /* Remove Bootstrap padding */
background: #e9ecef !important;
border-radius: 1.7em;
border: 1px solid #e9ecef !important;
box-shadow: none;
/* You can adjust height/width for your visual design */
}
/* Target the caret in the dropdown toggle and move it left and down */
.custom-drop-down-btn .dropdown-toggle::after {
margin-left: 0 !important; /* Remove any left margin */
transform: translate(0, 2px); /* Move caret left (0px) and down (+2px) */
/* Try larger/smaller values if needed */
}
/* If you want to be very precise... */
.custom-drop-down-btn .dropdown-toggle {
display: flex;
align-items: center;
justify-content: center;
padding: 0 !important;
}
@media (max-width: 640px) {
.spaceing,
.first {

View File

@ -1,5 +1,5 @@
import React, { useRef } from "react";
import { Navbar, Nav, Dropdown, DropdownButton } from "react-bootstrap";
import { Navbar, Nav, Dropdown } from "react-bootstrap";
import { Link } from "react-router-dom";
import { VscHome } from "react-icons/vsc";
import { FaFacebook } from "react-icons/fa";
@ -14,10 +14,9 @@ import { useEffect } from "react";
import { handleClickLink } from "./helper";
import { linkUpdated } from "../features/link/linkSlice";
import { friendsListPageSet } from "../features/accountPage/accountPageSlice";
import CustomToggle from "./CustomToggle";
const TitleBar = (props) => {
const TitleBar = () => {
const refs = {
home: useRef(null),
friends: useRef(null),
@ -50,83 +49,98 @@ const TitleBar = (props) => {
}
return (
<div className="titlebar bg-light">
<Navbar bg="light" className="p-0 nav-container">
<Navbar.Brand as={Link} to="/fakebook">
<FaFacebook color="dodgerblue" fontSize="2em" className="mx-3" />
<div className='titlebar bg-light'>
<Navbar bg='light' className='p-0 nav-container'>
<Navbar.Brand as={Link} to='/' aria-label='fakebook'>
<FaFacebook color='dodgerblue' fontSize='2em' className='mx-3' />
</Navbar.Brand>
<div style={{ width: "450px" }} className="spaceing" />
<Nav className="w-75 justify-content-start mr-5">
<Nav.Item className="first">
<Link to="/fakebook" className="nav-link" ref={refs.home}>
<div style={{ width: "450px" }} className='spaceing' />
<Nav className='w-75 justify-content-start mr-5'>
<Nav.Item className='first'>
<Link to='/' className='nav-link' ref={refs.home} aria-label='home'>
<VscHome
fontSize="2rem"
className="mx-4"
fontSize='2rem'
className='mx-4'
style={{ pointerEvents: "none" }}
/>
</Link>
</Nav.Item>
<Nav.Item>
<Link
to="/fakebook/friends/list"
className="nav-link"
ref={refs.friends}>
to='/friends/list'
className='nav-link'
ref={refs.friends}
aria-label='friends list'
>
<FaUserFriends
fontSize="2rem"
className="mx-4"
fontSize='2rem'
className='mx-4'
style={{ pointerEvents: "none" }}
/>
</Link>
</Nav.Item>
<Nav.Item>
<Link to="/fakebook/watch" className="nav-link" ref={refs.watch}>
<Link
to='/watch'
className='nav-link'
ref={refs.watch}
aria-label='videos'
>
<MdOndemandVideo
fontSize="2rem"
className="mx-4"
fontSize='2rem'
className='mx-4'
style={{ pointerEvents: "none" }}
/>
</Link>
</Nav.Item>
</Nav>
<Nav className="w-25 justify-content-end align-self-center">
<Nav.Item className="align-self-center first">
<Nav className='w-25 justify-content-end align-self-center'>
<Nav.Item className='align-self-center first'>
<Link
to={profileLink}
className="nav-link profile"
id="profile"
className='nav-link profile'
id='profile'
onClick={closeFriendsListPage}
ref={refs.profile}>
<ProfileLink user={user} size="30" fullname="false" bold="true" />
ref={refs.profile}
>
<ProfileLink user={user} size='30' fullname='false' bold='true' />
</Link>
</Nav.Item>
<Nav.Item className="align-self-center">
<DropdownButton
title=""
className="mr-4 custom-drop-down-btn"
menuAlign="right">
<Nav.Item className='align-self-center'>
<Dropdown className='mr-4 custom-drop-down-btn'>
<Dropdown.Toggle as={CustomToggle} />
<Dropdown.Menu alignRight>
<Dropdown.Item
as={Link}
to={profileLink}
onClick={closeFriendsListPage}>
onClick={closeFriendsListPage}
>
<ProfileLink
user={user}
size="60"
fullname="true"
bold="true"
size='60'
fullname='true'
bold='true'
/>
</Dropdown.Item>
<Dropdown.Divider />
<Dropdown.Item
as={Link}
to="/fakebook/"
to='/'
onClick={handleClick}
className="p-0">
<ImExit fontSize="1.5em" className="mx-4" />
className='p-0'
>
<ImExit fontSize='1.5em' className='mx-4' />
<span>Log Out</span>
<div style={{ width: "20em" }}></div>
</Dropdown.Item>
</DropdownButton>
</Dropdown.Menu>
</Dropdown>
</Nav.Item>
</Nav>
</Navbar>

View File

@ -38,7 +38,6 @@ import {
/* Mock-backend helpers */
import {
currentUserOffline,
currentUserOnline,
subscribeCurrentUser,
subscribeUsers,
@ -56,16 +55,24 @@ const RouteStateSync = () => {
const location = useLocation();
const isFriendsListPage = useSelector(
(state) => state.accountPage.isFriendsListPage
);
useEffect(() => {
const { pathname } = location;
/* friends list page */
dispatch(friendsListPageSet(pathname.startsWith("/fakebook/friends/list")));
dispatch(
friendsListPageSet(
pathname.startsWith("/friends/list") || isFriendsListPage
)
);
/* watch page (videos feed) */
dispatch(watchSet(pathname.startsWith("/fakebook/watch")));
dispatch(watchSet(pathname.startsWith("/watch")));
}, [location, dispatch]);
return null; // renders nothing
@ -84,9 +91,13 @@ const UserAccount = () => {
const users = useSelector((state) => state.users);
const isFriendsListPage = useSelector(
(state) => state.accountPage.isFriendsListPage
);
/* -------------------------------------------------- */
/* Firestore-like subscriptions & online/offline flag */
/* Firestore-like subscriptions */
/* -------------------------------------------------- */
@ -101,21 +112,6 @@ const UserAccount = () => {
currentUserOnline();
/* window closed or refreshed */
const beforeUnload = () => currentUserOffline();
window.addEventListener("beforeunload", beforeUnload);
/* tab visibility switch */
const visChange = () =>
document.visibilityState === "visible"
? currentUserOnline()
: currentUserOffline();
document.addEventListener("visibilitychange", visChange);
/* cleanup */
return () => {
@ -124,10 +120,6 @@ const UserAccount = () => {
unsubUsers();
unsubPosts();
window.removeEventListener("beforeunload", beforeUnload);
document.removeEventListener("visibilitychange", visChange);
};
}, []);
@ -167,7 +159,7 @@ const UserAccount = () => {
return (
<div className='bg-200 vw-100 main-container overflow-hidden'>
<Container className='w-100 p-0' fluid>
<Router>
<Router basename='/fakebook-aigen'>
<RouteStateSync />
<TitleBar />
@ -175,27 +167,30 @@ const UserAccount = () => {
<Switch>
{/* Friends list ------------------------------------------------ */}
<Route path='/fakebook/friends/list' component={FriendsListPage} />
<Route path='/friends/list' component={FriendsListPage} />
{/* Single photo ----------------------------------------------- */}
<Route path='/fakebook/photo/:userID/:n' component={PhotoViewer} />
<Route path='/photo/:userID/:n' component={PhotoViewer} />
{/* Watch (video feed) ----------------------------------------- */}
<Route
path='/fakebook/watch'
path='/watch'
render={(props) => <HomePage {...props} className='pt-5' />}
/>
{/* User profile ----------------------------------------------- */}
<Route path='/fakebook/:userName' component={Profile} />
<Route
path='/:userName'
component={isFriendsListPage ? FriendsListPage : Profile}
/>
{/* News-feed root --------------------------------------------- */}
<Route
path='/fakebook'
path='/'
exact
render={(props) => <HomePage {...props} className='pt-5' />}
/>

View File

@ -1,7 +1,8 @@
import { defineConfig } from 'vite'
import preact from '@preact/preset-vite'
import { defineConfig } from "vite";
import preact from "@preact/preset-vite";
// https://vite.dev/config/
export default defineConfig({
plugins: [preact()],
})
base: "/fakebook-aigen/", // <--- ADD THIS AS THE REPO NAME
});