Initial
							
								
								
									
										3
									
								
								.gitattributes
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,3 @@
 | 
				
			|||||||
 | 
					* text=auto eol=lf
 | 
				
			||||||
 | 
					*.{cmd,[cC][mM][dD]} text eol=crlf
 | 
				
			||||||
 | 
					*.{bat,[bB][aA][tT]} text eol=crlf
 | 
				
			||||||
							
								
								
									
										28
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,28 @@
 | 
				
			|||||||
 | 
					# Project specific
 | 
				
			||||||
 | 
					node_modules/
 | 
				
			||||||
 | 
					*.Identifier
 | 
				
			||||||
 | 
					.docusaurus
 | 
				
			||||||
 | 
					build
 | 
				
			||||||
 | 
					.vercel
 | 
				
			||||||
 | 
					.env
 | 
				
			||||||
 | 
					.pnpm-debug.log
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# macOS
 | 
				
			||||||
 | 
					.DS_Store
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# IntelliJ
 | 
				
			||||||
 | 
					.idea
 | 
				
			||||||
 | 
					*.iml
 | 
				
			||||||
 | 
					out
 | 
				
			||||||
 | 
					gen
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# VS Code
 | 
				
			||||||
 | 
					.vscode/*
 | 
				
			||||||
 | 
					!.vscode/settings.json
 | 
				
			||||||
 | 
					!.vscode/tasks.json
 | 
				
			||||||
 | 
					!.vscode/launch.json
 | 
				
			||||||
 | 
					!.vscode/extensions.json
 | 
				
			||||||
 | 
					!.vscode/*.code-snippets
 | 
				
			||||||
 | 
					.history/
 | 
				
			||||||
 | 
					*.vsix
 | 
				
			||||||
 | 
					*.code-workspace
 | 
				
			||||||
							
								
								
									
										7
									
								
								.trunk/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,7 @@
 | 
				
			|||||||
 | 
					*out
 | 
				
			||||||
 | 
					*logs
 | 
				
			||||||
 | 
					*actions
 | 
				
			||||||
 | 
					*notifications
 | 
				
			||||||
 | 
					plugins
 | 
				
			||||||
 | 
					user_trunk.yaml
 | 
				
			||||||
 | 
					user.yaml
 | 
				
			||||||
							
								
								
									
										10
									
								
								.trunk/configs/.markdownlint.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,10 @@
 | 
				
			|||||||
 | 
					# Autoformatter friendly markdownlint config (all formatting rules disabled)
 | 
				
			||||||
 | 
					default: true
 | 
				
			||||||
 | 
					blank_lines: false
 | 
				
			||||||
 | 
					bullet: false
 | 
				
			||||||
 | 
					html: false
 | 
				
			||||||
 | 
					indentation: false
 | 
				
			||||||
 | 
					line_length: false
 | 
				
			||||||
 | 
					spaces: false
 | 
				
			||||||
 | 
					url: false
 | 
				
			||||||
 | 
					whitespace: false
 | 
				
			||||||
							
								
								
									
										7
									
								
								.trunk/configs/.shellcheckrc
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,7 @@
 | 
				
			|||||||
 | 
					enable=all
 | 
				
			||||||
 | 
					source-path=SCRIPTDIR
 | 
				
			||||||
 | 
					disable=SC2154
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# If you're having issues with shellcheck following source, disable the errors via:
 | 
				
			||||||
 | 
					# disable=SC1090
 | 
				
			||||||
 | 
					# disable=SC1091
 | 
				
			||||||
							
								
								
									
										17
									
								
								.trunk/configs/rome.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,17 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					  "$schema": "../../node_modules/rome/configuration_schema.json",
 | 
				
			||||||
 | 
					  "formatter": {
 | 
				
			||||||
 | 
					    "enabled": true,
 | 
				
			||||||
 | 
					    "indentStyle": "space",
 | 
				
			||||||
 | 
					    "indentSize": 2
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  "linter": {
 | 
				
			||||||
 | 
					    "enabled": true,
 | 
				
			||||||
 | 
					    "rules": {
 | 
				
			||||||
 | 
					      "recommended": true
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  "organizeImports": {
 | 
				
			||||||
 | 
					    "enabled": true
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										14
									
								
								.trunk/configs/svgo.config.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,14 @@
 | 
				
			|||||||
 | 
					module.exports = {
 | 
				
			||||||
 | 
						plugins: [
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name: "preset-default",
 | 
				
			||||||
 | 
								params: {
 | 
				
			||||||
 | 
									overrides: {
 | 
				
			||||||
 | 
										removeViewBox: false, // https://github.com/svg/svgo/issues/1128
 | 
				
			||||||
 | 
										sortAttrs: true,
 | 
				
			||||||
 | 
										removeOffCanvasPaths: true,
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						],
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
							
								
								
									
										25
									
								
								.trunk/trunk.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,25 @@
 | 
				
			|||||||
 | 
					version: 0.1
 | 
				
			||||||
 | 
					cli:
 | 
				
			||||||
 | 
					  version: 1.3.1
 | 
				
			||||||
 | 
					plugins:
 | 
				
			||||||
 | 
					  sources:
 | 
				
			||||||
 | 
					    - id: trunk
 | 
				
			||||||
 | 
					      ref: v0.0.8
 | 
				
			||||||
 | 
					      uri: https://github.com/trunk-io/plugins
 | 
				
			||||||
 | 
					lint:
 | 
				
			||||||
 | 
					  disabled:
 | 
				
			||||||
 | 
					    - eslint
 | 
				
			||||||
 | 
					    - prettier
 | 
				
			||||||
 | 
					  enabled:
 | 
				
			||||||
 | 
					    - rome@12.0.0
 | 
				
			||||||
 | 
					    - markdownlint@0.33.0
 | 
				
			||||||
 | 
					    - actionlint@1.6.22
 | 
				
			||||||
 | 
					    - gitleaks@8.15.2
 | 
				
			||||||
 | 
					    - git-diff-check
 | 
				
			||||||
 | 
					    - shellcheck@0.9.0
 | 
				
			||||||
 | 
					    - shfmt@3.5.0
 | 
				
			||||||
 | 
					    - svgo@3.0.2
 | 
				
			||||||
 | 
					runtimes:
 | 
				
			||||||
 | 
					  enabled:
 | 
				
			||||||
 | 
					    - go@1.18.3
 | 
				
			||||||
 | 
					    - node@18.12.1
 | 
				
			||||||
							
								
								
									
										3
									
								
								.vscode/extensions.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,3 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					  "recommendations": ["trunk.io"]
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										7
									
								
								.vscode/settings.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,7 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					  "editor.formatOnSave": true,
 | 
				
			||||||
 | 
					  "editor.defaultFormatter": "trunk.io",
 | 
				
			||||||
 | 
					  "files.associations": {
 | 
				
			||||||
 | 
					    "*.mdx": "markdown"
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										674
									
								
								LICENSE
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,674 @@
 | 
				
			|||||||
 | 
					                    GNU GENERAL PUBLIC LICENSE
 | 
				
			||||||
 | 
					                       Version 3, 29 June 2007
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
 | 
				
			||||||
 | 
					 Everyone is permitted to copy and distribute verbatim copies
 | 
				
			||||||
 | 
					 of this license document, but changing it is not allowed.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                            Preamble
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  The GNU General Public License is a free, copyleft license for
 | 
				
			||||||
 | 
					software and other kinds of works.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  The licenses for most software and other practical works are designed
 | 
				
			||||||
 | 
					to take away your freedom to share and change the works.  By contrast,
 | 
				
			||||||
 | 
					the GNU General Public License is intended to guarantee your freedom to
 | 
				
			||||||
 | 
					share and change all versions of a program--to make sure it remains free
 | 
				
			||||||
 | 
					software for all its users.  We, the Free Software Foundation, use the
 | 
				
			||||||
 | 
					GNU General Public License for most of our software; it applies also to
 | 
				
			||||||
 | 
					any other work released this way by its authors.  You can apply it to
 | 
				
			||||||
 | 
					your programs, too.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  When we speak of free software, we are referring to freedom, not
 | 
				
			||||||
 | 
					price.  Our General Public Licenses are designed to make sure that you
 | 
				
			||||||
 | 
					have the freedom to distribute copies of free software (and charge for
 | 
				
			||||||
 | 
					them if you wish), that you receive source code or can get it if you
 | 
				
			||||||
 | 
					want it, that you can change the software or use pieces of it in new
 | 
				
			||||||
 | 
					free programs, and that you know you can do these things.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  To protect your rights, we need to prevent others from denying you
 | 
				
			||||||
 | 
					these rights or asking you to surrender the rights.  Therefore, you have
 | 
				
			||||||
 | 
					certain responsibilities if you distribute copies of the software, or if
 | 
				
			||||||
 | 
					you modify it: responsibilities to respect the freedom of others.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  For example, if you distribute copies of such a program, whether
 | 
				
			||||||
 | 
					gratis or for a fee, you must pass on to the recipients the same
 | 
				
			||||||
 | 
					freedoms that you received.  You must make sure that they, too, receive
 | 
				
			||||||
 | 
					or can get the source code.  And you must show them these terms so they
 | 
				
			||||||
 | 
					know their rights.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Developers that use the GNU GPL protect your rights with two steps:
 | 
				
			||||||
 | 
					(1) assert copyright on the software, and (2) offer you this License
 | 
				
			||||||
 | 
					giving you legal permission to copy, distribute and/or modify it.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  For the developers' and authors' protection, the GPL clearly explains
 | 
				
			||||||
 | 
					that there is no warranty for this free software.  For both users' and
 | 
				
			||||||
 | 
					authors' sake, the GPL requires that modified versions be marked as
 | 
				
			||||||
 | 
					changed, so that their problems will not be attributed erroneously to
 | 
				
			||||||
 | 
					authors of previous versions.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Some devices are designed to deny users access to install or run
 | 
				
			||||||
 | 
					modified versions of the software inside them, although the manufacturer
 | 
				
			||||||
 | 
					can do so.  This is fundamentally incompatible with the aim of
 | 
				
			||||||
 | 
					protecting users' freedom to change the software.  The systematic
 | 
				
			||||||
 | 
					pattern of such abuse occurs in the area of products for individuals to
 | 
				
			||||||
 | 
					use, which is precisely where it is most unacceptable.  Therefore, we
 | 
				
			||||||
 | 
					have designed this version of the GPL to prohibit the practice for those
 | 
				
			||||||
 | 
					products.  If such problems arise substantially in other domains, we
 | 
				
			||||||
 | 
					stand ready to extend this provision to those domains in future versions
 | 
				
			||||||
 | 
					of the GPL, as needed to protect the freedom of users.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Finally, every program is threatened constantly by software patents.
 | 
				
			||||||
 | 
					States should not allow patents to restrict development and use of
 | 
				
			||||||
 | 
					software on general-purpose computers, but in those that do, we wish to
 | 
				
			||||||
 | 
					avoid the special danger that patents applied to a free program could
 | 
				
			||||||
 | 
					make it effectively proprietary.  To prevent this, the GPL assures that
 | 
				
			||||||
 | 
					patents cannot be used to render the program non-free.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  The precise terms and conditions for copying, distribution and
 | 
				
			||||||
 | 
					modification follow.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                       TERMS AND CONDITIONS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  0. Definitions.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  "This License" refers to version 3 of the GNU General Public License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  "Copyright" also means copyright-like laws that apply to other kinds of
 | 
				
			||||||
 | 
					works, such as semiconductor masks.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  "The Program" refers to any copyrightable work licensed under this
 | 
				
			||||||
 | 
					License.  Each licensee is addressed as "you".  "Licensees" and
 | 
				
			||||||
 | 
					"recipients" may be individuals or organizations.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  To "modify" a work means to copy from or adapt all or part of the work
 | 
				
			||||||
 | 
					in a fashion requiring copyright permission, other than the making of an
 | 
				
			||||||
 | 
					exact copy.  The resulting work is called a "modified version" of the
 | 
				
			||||||
 | 
					earlier work or a work "based on" the earlier work.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  A "covered work" means either the unmodified Program or a work based
 | 
				
			||||||
 | 
					on the Program.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  To "propagate" a work means to do anything with it that, without
 | 
				
			||||||
 | 
					permission, would make you directly or secondarily liable for
 | 
				
			||||||
 | 
					infringement under applicable copyright law, except executing it on a
 | 
				
			||||||
 | 
					computer or modifying a private copy.  Propagation includes copying,
 | 
				
			||||||
 | 
					distribution (with or without modification), making available to the
 | 
				
			||||||
 | 
					public, and in some countries other activities as well.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  To "convey" a work means any kind of propagation that enables other
 | 
				
			||||||
 | 
					parties to make or receive copies.  Mere interaction with a user through
 | 
				
			||||||
 | 
					a computer network, with no transfer of a copy, is not conveying.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  An interactive user interface displays "Appropriate Legal Notices"
 | 
				
			||||||
 | 
					to the extent that it includes a convenient and prominently visible
 | 
				
			||||||
 | 
					feature that (1) displays an appropriate copyright notice, and (2)
 | 
				
			||||||
 | 
					tells the user that there is no warranty for the work (except to the
 | 
				
			||||||
 | 
					extent that warranties are provided), that licensees may convey the
 | 
				
			||||||
 | 
					work under this License, and how to view a copy of this License.  If
 | 
				
			||||||
 | 
					the interface presents a list of user commands or options, such as a
 | 
				
			||||||
 | 
					menu, a prominent item in the list meets this criterion.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  1. Source Code.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  The "source code" for a work means the preferred form of the work
 | 
				
			||||||
 | 
					for making modifications to it.  "Object code" means any non-source
 | 
				
			||||||
 | 
					form of a work.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  A "Standard Interface" means an interface that either is an official
 | 
				
			||||||
 | 
					standard defined by a recognized standards body, or, in the case of
 | 
				
			||||||
 | 
					interfaces specified for a particular programming language, one that
 | 
				
			||||||
 | 
					is widely used among developers working in that language.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  The "System Libraries" of an executable work include anything, other
 | 
				
			||||||
 | 
					than the work as a whole, that (a) is included in the normal form of
 | 
				
			||||||
 | 
					packaging a Major Component, but which is not part of that Major
 | 
				
			||||||
 | 
					Component, and (b) serves only to enable use of the work with that
 | 
				
			||||||
 | 
					Major Component, or to implement a Standard Interface for which an
 | 
				
			||||||
 | 
					implementation is available to the public in source code form.  A
 | 
				
			||||||
 | 
					"Major Component", in this context, means a major essential component
 | 
				
			||||||
 | 
					(kernel, window system, and so on) of the specific operating system
 | 
				
			||||||
 | 
					(if any) on which the executable work runs, or a compiler used to
 | 
				
			||||||
 | 
					produce the work, or an object code interpreter used to run it.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  The "Corresponding Source" for a work in object code form means all
 | 
				
			||||||
 | 
					the source code needed to generate, install, and (for an executable
 | 
				
			||||||
 | 
					work) run the object code and to modify the work, including scripts to
 | 
				
			||||||
 | 
					control those activities.  However, it does not include the work's
 | 
				
			||||||
 | 
					System Libraries, or general-purpose tools or generally available free
 | 
				
			||||||
 | 
					programs which are used unmodified in performing those activities but
 | 
				
			||||||
 | 
					which are not part of the work.  For example, Corresponding Source
 | 
				
			||||||
 | 
					includes interface definition files associated with source files for
 | 
				
			||||||
 | 
					the work, and the source code for shared libraries and dynamically
 | 
				
			||||||
 | 
					linked subprograms that the work is specifically designed to require,
 | 
				
			||||||
 | 
					such as by intimate data communication or control flow between those
 | 
				
			||||||
 | 
					subprograms and other parts of the work.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  The Corresponding Source need not include anything that users
 | 
				
			||||||
 | 
					can regenerate automatically from other parts of the Corresponding
 | 
				
			||||||
 | 
					Source.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  The Corresponding Source for a work in source code form is that
 | 
				
			||||||
 | 
					same work.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  2. Basic Permissions.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  All rights granted under this License are granted for the term of
 | 
				
			||||||
 | 
					copyright on the Program, and are irrevocable provided the stated
 | 
				
			||||||
 | 
					conditions are met.  This License explicitly affirms your unlimited
 | 
				
			||||||
 | 
					permission to run the unmodified Program.  The output from running a
 | 
				
			||||||
 | 
					covered work is covered by this License only if the output, given its
 | 
				
			||||||
 | 
					content, constitutes a covered work.  This License acknowledges your
 | 
				
			||||||
 | 
					rights of fair use or other equivalent, as provided by copyright law.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  You may make, run and propagate covered works that you do not
 | 
				
			||||||
 | 
					convey, without conditions so long as your license otherwise remains
 | 
				
			||||||
 | 
					in force.  You may convey covered works to others for the sole purpose
 | 
				
			||||||
 | 
					of having them make modifications exclusively for you, or provide you
 | 
				
			||||||
 | 
					with facilities for running those works, provided that you comply with
 | 
				
			||||||
 | 
					the terms of this License in conveying all material for which you do
 | 
				
			||||||
 | 
					not control copyright.  Those thus making or running the covered works
 | 
				
			||||||
 | 
					for you must do so exclusively on your behalf, under your direction
 | 
				
			||||||
 | 
					and control, on terms that prohibit them from making any copies of
 | 
				
			||||||
 | 
					your copyrighted material outside their relationship with you.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Conveying under any other circumstances is permitted solely under
 | 
				
			||||||
 | 
					the conditions stated below.  Sublicensing is not allowed; section 10
 | 
				
			||||||
 | 
					makes it unnecessary.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  3. Protecting Users' Legal Rights From Anti-Circumvention Law.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  No covered work shall be deemed part of an effective technological
 | 
				
			||||||
 | 
					measure under any applicable law fulfilling obligations under article
 | 
				
			||||||
 | 
					11 of the WIPO copyright treaty adopted on 20 December 1996, or
 | 
				
			||||||
 | 
					similar laws prohibiting or restricting circumvention of such
 | 
				
			||||||
 | 
					measures.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  When you convey a covered work, you waive any legal power to forbid
 | 
				
			||||||
 | 
					circumvention of technological measures to the extent such circumvention
 | 
				
			||||||
 | 
					is effected by exercising rights under this License with respect to
 | 
				
			||||||
 | 
					the covered work, and you disclaim any intention to limit operation or
 | 
				
			||||||
 | 
					modification of the work as a means of enforcing, against the work's
 | 
				
			||||||
 | 
					users, your or third parties' legal rights to forbid circumvention of
 | 
				
			||||||
 | 
					technological measures.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  4. Conveying Verbatim Copies.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  You may convey verbatim copies of the Program's source code as you
 | 
				
			||||||
 | 
					receive it, in any medium, provided that you conspicuously and
 | 
				
			||||||
 | 
					appropriately publish on each copy an appropriate copyright notice;
 | 
				
			||||||
 | 
					keep intact all notices stating that this License and any
 | 
				
			||||||
 | 
					non-permissive terms added in accord with section 7 apply to the code;
 | 
				
			||||||
 | 
					keep intact all notices of the absence of any warranty; and give all
 | 
				
			||||||
 | 
					recipients a copy of this License along with the Program.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  You may charge any price or no price for each copy that you convey,
 | 
				
			||||||
 | 
					and you may offer support or warranty protection for a fee.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  5. Conveying Modified Source Versions.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  You may convey a work based on the Program, or the modifications to
 | 
				
			||||||
 | 
					produce it from the Program, in the form of source code under the
 | 
				
			||||||
 | 
					terms of section 4, provided that you also meet all of these conditions:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    a) The work must carry prominent notices stating that you modified
 | 
				
			||||||
 | 
					    it, and giving a relevant date.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    b) The work must carry prominent notices stating that it is
 | 
				
			||||||
 | 
					    released under this License and any conditions added under section
 | 
				
			||||||
 | 
					    7.  This requirement modifies the requirement in section 4 to
 | 
				
			||||||
 | 
					    "keep intact all notices".
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    c) You must license the entire work, as a whole, under this
 | 
				
			||||||
 | 
					    License to anyone who comes into possession of a copy.  This
 | 
				
			||||||
 | 
					    License will therefore apply, along with any applicable section 7
 | 
				
			||||||
 | 
					    additional terms, to the whole of the work, and all its parts,
 | 
				
			||||||
 | 
					    regardless of how they are packaged.  This License gives no
 | 
				
			||||||
 | 
					    permission to license the work in any other way, but it does not
 | 
				
			||||||
 | 
					    invalidate such permission if you have separately received it.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    d) If the work has interactive user interfaces, each must display
 | 
				
			||||||
 | 
					    Appropriate Legal Notices; however, if the Program has interactive
 | 
				
			||||||
 | 
					    interfaces that do not display Appropriate Legal Notices, your
 | 
				
			||||||
 | 
					    work need not make them do so.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  A compilation of a covered work with other separate and independent
 | 
				
			||||||
 | 
					works, which are not by their nature extensions of the covered work,
 | 
				
			||||||
 | 
					and which are not combined with it such as to form a larger program,
 | 
				
			||||||
 | 
					in or on a volume of a storage or distribution medium, is called an
 | 
				
			||||||
 | 
					"aggregate" if the compilation and its resulting copyright are not
 | 
				
			||||||
 | 
					used to limit the access or legal rights of the compilation's users
 | 
				
			||||||
 | 
					beyond what the individual works permit.  Inclusion of a covered work
 | 
				
			||||||
 | 
					in an aggregate does not cause this License to apply to the other
 | 
				
			||||||
 | 
					parts of the aggregate.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  6. Conveying Non-Source Forms.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  You may convey a covered work in object code form under the terms
 | 
				
			||||||
 | 
					of sections 4 and 5, provided that you also convey the
 | 
				
			||||||
 | 
					machine-readable Corresponding Source under the terms of this License,
 | 
				
			||||||
 | 
					in one of these ways:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    a) Convey the object code in, or embodied in, a physical product
 | 
				
			||||||
 | 
					    (including a physical distribution medium), accompanied by the
 | 
				
			||||||
 | 
					    Corresponding Source fixed on a durable physical medium
 | 
				
			||||||
 | 
					    customarily used for software interchange.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    b) Convey the object code in, or embodied in, a physical product
 | 
				
			||||||
 | 
					    (including a physical distribution medium), accompanied by a
 | 
				
			||||||
 | 
					    written offer, valid for at least three years and valid for as
 | 
				
			||||||
 | 
					    long as you offer spare parts or customer support for that product
 | 
				
			||||||
 | 
					    model, to give anyone who possesses the object code either (1) a
 | 
				
			||||||
 | 
					    copy of the Corresponding Source for all the software in the
 | 
				
			||||||
 | 
					    product that is covered by this License, on a durable physical
 | 
				
			||||||
 | 
					    medium customarily used for software interchange, for a price no
 | 
				
			||||||
 | 
					    more than your reasonable cost of physically performing this
 | 
				
			||||||
 | 
					    conveying of source, or (2) access to copy the
 | 
				
			||||||
 | 
					    Corresponding Source from a network server at no charge.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    c) Convey individual copies of the object code with a copy of the
 | 
				
			||||||
 | 
					    written offer to provide the Corresponding Source.  This
 | 
				
			||||||
 | 
					    alternative is allowed only occasionally and noncommercially, and
 | 
				
			||||||
 | 
					    only if you received the object code with such an offer, in accord
 | 
				
			||||||
 | 
					    with subsection 6b.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    d) Convey the object code by offering access from a designated
 | 
				
			||||||
 | 
					    place (gratis or for a charge), and offer equivalent access to the
 | 
				
			||||||
 | 
					    Corresponding Source in the same way through the same place at no
 | 
				
			||||||
 | 
					    further charge.  You need not require recipients to copy the
 | 
				
			||||||
 | 
					    Corresponding Source along with the object code.  If the place to
 | 
				
			||||||
 | 
					    copy the object code is a network server, the Corresponding Source
 | 
				
			||||||
 | 
					    may be on a different server (operated by you or a third party)
 | 
				
			||||||
 | 
					    that supports equivalent copying facilities, provided you maintain
 | 
				
			||||||
 | 
					    clear directions next to the object code saying where to find the
 | 
				
			||||||
 | 
					    Corresponding Source.  Regardless of what server hosts the
 | 
				
			||||||
 | 
					    Corresponding Source, you remain obligated to ensure that it is
 | 
				
			||||||
 | 
					    available for as long as needed to satisfy these requirements.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    e) Convey the object code using peer-to-peer transmission, provided
 | 
				
			||||||
 | 
					    you inform other peers where the object code and Corresponding
 | 
				
			||||||
 | 
					    Source of the work are being offered to the general public at no
 | 
				
			||||||
 | 
					    charge under subsection 6d.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  A separable portion of the object code, whose source code is excluded
 | 
				
			||||||
 | 
					from the Corresponding Source as a System Library, need not be
 | 
				
			||||||
 | 
					included in conveying the object code work.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  A "User Product" is either (1) a "consumer product", which means any
 | 
				
			||||||
 | 
					tangible personal property which is normally used for personal, family,
 | 
				
			||||||
 | 
					or household purposes, or (2) anything designed or sold for incorporation
 | 
				
			||||||
 | 
					into a dwelling.  In determining whether a product is a consumer product,
 | 
				
			||||||
 | 
					doubtful cases shall be resolved in favor of coverage.  For a particular
 | 
				
			||||||
 | 
					product received by a particular user, "normally used" refers to a
 | 
				
			||||||
 | 
					typical or common use of that class of product, regardless of the status
 | 
				
			||||||
 | 
					of the particular user or of the way in which the particular user
 | 
				
			||||||
 | 
					actually uses, or expects or is expected to use, the product.  A product
 | 
				
			||||||
 | 
					is a consumer product regardless of whether the product has substantial
 | 
				
			||||||
 | 
					commercial, industrial or non-consumer uses, unless such uses represent
 | 
				
			||||||
 | 
					the only significant mode of use of the product.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  "Installation Information" for a User Product means any methods,
 | 
				
			||||||
 | 
					procedures, authorization keys, or other information required to install
 | 
				
			||||||
 | 
					and execute modified versions of a covered work in that User Product from
 | 
				
			||||||
 | 
					a modified version of its Corresponding Source.  The information must
 | 
				
			||||||
 | 
					suffice to ensure that the continued functioning of the modified object
 | 
				
			||||||
 | 
					code is in no case prevented or interfered with solely because
 | 
				
			||||||
 | 
					modification has been made.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  If you convey an object code work under this section in, or with, or
 | 
				
			||||||
 | 
					specifically for use in, a User Product, and the conveying occurs as
 | 
				
			||||||
 | 
					part of a transaction in which the right of possession and use of the
 | 
				
			||||||
 | 
					User Product is transferred to the recipient in perpetuity or for a
 | 
				
			||||||
 | 
					fixed term (regardless of how the transaction is characterized), the
 | 
				
			||||||
 | 
					Corresponding Source conveyed under this section must be accompanied
 | 
				
			||||||
 | 
					by the Installation Information.  But this requirement does not apply
 | 
				
			||||||
 | 
					if neither you nor any third party retains the ability to install
 | 
				
			||||||
 | 
					modified object code on the User Product (for example, the work has
 | 
				
			||||||
 | 
					been installed in ROM).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  The requirement to provide Installation Information does not include a
 | 
				
			||||||
 | 
					requirement to continue to provide support service, warranty, or updates
 | 
				
			||||||
 | 
					for a work that has been modified or installed by the recipient, or for
 | 
				
			||||||
 | 
					the User Product in which it has been modified or installed.  Access to a
 | 
				
			||||||
 | 
					network may be denied when the modification itself materially and
 | 
				
			||||||
 | 
					adversely affects the operation of the network or violates the rules and
 | 
				
			||||||
 | 
					protocols for communication across the network.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Corresponding Source conveyed, and Installation Information provided,
 | 
				
			||||||
 | 
					in accord with this section must be in a format that is publicly
 | 
				
			||||||
 | 
					documented (and with an implementation available to the public in
 | 
				
			||||||
 | 
					source code form), and must require no special password or key for
 | 
				
			||||||
 | 
					unpacking, reading or copying.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  7. Additional Terms.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  "Additional permissions" are terms that supplement the terms of this
 | 
				
			||||||
 | 
					License by making exceptions from one or more of its conditions.
 | 
				
			||||||
 | 
					Additional permissions that are applicable to the entire Program shall
 | 
				
			||||||
 | 
					be treated as though they were included in this License, to the extent
 | 
				
			||||||
 | 
					that they are valid under applicable law.  If additional permissions
 | 
				
			||||||
 | 
					apply only to part of the Program, that part may be used separately
 | 
				
			||||||
 | 
					under those permissions, but the entire Program remains governed by
 | 
				
			||||||
 | 
					this License without regard to the additional permissions.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  When you convey a copy of a covered work, you may at your option
 | 
				
			||||||
 | 
					remove any additional permissions from that copy, or from any part of
 | 
				
			||||||
 | 
					it.  (Additional permissions may be written to require their own
 | 
				
			||||||
 | 
					removal in certain cases when you modify the work.)  You may place
 | 
				
			||||||
 | 
					additional permissions on material, added by you to a covered work,
 | 
				
			||||||
 | 
					for which you have or can give appropriate copyright permission.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Notwithstanding any other provision of this License, for material you
 | 
				
			||||||
 | 
					add to a covered work, you may (if authorized by the copyright holders of
 | 
				
			||||||
 | 
					that material) supplement the terms of this License with terms:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    a) Disclaiming warranty or limiting liability differently from the
 | 
				
			||||||
 | 
					    terms of sections 15 and 16 of this License; or
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    b) Requiring preservation of specified reasonable legal notices or
 | 
				
			||||||
 | 
					    author attributions in that material or in the Appropriate Legal
 | 
				
			||||||
 | 
					    Notices displayed by works containing it; or
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    c) Prohibiting misrepresentation of the origin of that material, or
 | 
				
			||||||
 | 
					    requiring that modified versions of such material be marked in
 | 
				
			||||||
 | 
					    reasonable ways as different from the original version; or
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    d) Limiting the use for publicity purposes of names of licensors or
 | 
				
			||||||
 | 
					    authors of the material; or
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    e) Declining to grant rights under trademark law for use of some
 | 
				
			||||||
 | 
					    trade names, trademarks, or service marks; or
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    f) Requiring indemnification of licensors and authors of that
 | 
				
			||||||
 | 
					    material by anyone who conveys the material (or modified versions of
 | 
				
			||||||
 | 
					    it) with contractual assumptions of liability to the recipient, for
 | 
				
			||||||
 | 
					    any liability that these contractual assumptions directly impose on
 | 
				
			||||||
 | 
					    those licensors and authors.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  All other non-permissive additional terms are considered "further
 | 
				
			||||||
 | 
					restrictions" within the meaning of section 10.  If the Program as you
 | 
				
			||||||
 | 
					received it, or any part of it, contains a notice stating that it is
 | 
				
			||||||
 | 
					governed by this License along with a term that is a further
 | 
				
			||||||
 | 
					restriction, you may remove that term.  If a license document contains
 | 
				
			||||||
 | 
					a further restriction but permits relicensing or conveying under this
 | 
				
			||||||
 | 
					License, you may add to a covered work material governed by the terms
 | 
				
			||||||
 | 
					of that license document, provided that the further restriction does
 | 
				
			||||||
 | 
					not survive such relicensing or conveying.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  If you add terms to a covered work in accord with this section, you
 | 
				
			||||||
 | 
					must place, in the relevant source files, a statement of the
 | 
				
			||||||
 | 
					additional terms that apply to those files, or a notice indicating
 | 
				
			||||||
 | 
					where to find the applicable terms.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Additional terms, permissive or non-permissive, may be stated in the
 | 
				
			||||||
 | 
					form of a separately written license, or stated as exceptions;
 | 
				
			||||||
 | 
					the above requirements apply either way.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  8. Termination.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  You may not propagate or modify a covered work except as expressly
 | 
				
			||||||
 | 
					provided under this License.  Any attempt otherwise to propagate or
 | 
				
			||||||
 | 
					modify it is void, and will automatically terminate your rights under
 | 
				
			||||||
 | 
					this License (including any patent licenses granted under the third
 | 
				
			||||||
 | 
					paragraph of section 11).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  However, if you cease all violation of this License, then your
 | 
				
			||||||
 | 
					license from a particular copyright holder is reinstated (a)
 | 
				
			||||||
 | 
					provisionally, unless and until the copyright holder explicitly and
 | 
				
			||||||
 | 
					finally terminates your license, and (b) permanently, if the copyright
 | 
				
			||||||
 | 
					holder fails to notify you of the violation by some reasonable means
 | 
				
			||||||
 | 
					prior to 60 days after the cessation.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Moreover, your license from a particular copyright holder is
 | 
				
			||||||
 | 
					reinstated permanently if the copyright holder notifies you of the
 | 
				
			||||||
 | 
					violation by some reasonable means, this is the first time you have
 | 
				
			||||||
 | 
					received notice of violation of this License (for any work) from that
 | 
				
			||||||
 | 
					copyright holder, and you cure the violation prior to 30 days after
 | 
				
			||||||
 | 
					your receipt of the notice.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Termination of your rights under this section does not terminate the
 | 
				
			||||||
 | 
					licenses of parties who have received copies or rights from you under
 | 
				
			||||||
 | 
					this License.  If your rights have been terminated and not permanently
 | 
				
			||||||
 | 
					reinstated, you do not qualify to receive new licenses for the same
 | 
				
			||||||
 | 
					material under section 10.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  9. Acceptance Not Required for Having Copies.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  You are not required to accept this License in order to receive or
 | 
				
			||||||
 | 
					run a copy of the Program.  Ancillary propagation of a covered work
 | 
				
			||||||
 | 
					occurring solely as a consequence of using peer-to-peer transmission
 | 
				
			||||||
 | 
					to receive a copy likewise does not require acceptance.  However,
 | 
				
			||||||
 | 
					nothing other than this License grants you permission to propagate or
 | 
				
			||||||
 | 
					modify any covered work.  These actions infringe copyright if you do
 | 
				
			||||||
 | 
					not accept this License.  Therefore, by modifying or propagating a
 | 
				
			||||||
 | 
					covered work, you indicate your acceptance of this License to do so.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  10. Automatic Licensing of Downstream Recipients.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Each time you convey a covered work, the recipient automatically
 | 
				
			||||||
 | 
					receives a license from the original licensors, to run, modify and
 | 
				
			||||||
 | 
					propagate that work, subject to this License.  You are not responsible
 | 
				
			||||||
 | 
					for enforcing compliance by third parties with this License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  An "entity transaction" is a transaction transferring control of an
 | 
				
			||||||
 | 
					organization, or substantially all assets of one, or subdividing an
 | 
				
			||||||
 | 
					organization, or merging organizations.  If propagation of a covered
 | 
				
			||||||
 | 
					work results from an entity transaction, each party to that
 | 
				
			||||||
 | 
					transaction who receives a copy of the work also receives whatever
 | 
				
			||||||
 | 
					licenses to the work the party's predecessor in interest had or could
 | 
				
			||||||
 | 
					give under the previous paragraph, plus a right to possession of the
 | 
				
			||||||
 | 
					Corresponding Source of the work from the predecessor in interest, if
 | 
				
			||||||
 | 
					the predecessor has it or can get it with reasonable efforts.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  You may not impose any further restrictions on the exercise of the
 | 
				
			||||||
 | 
					rights granted or affirmed under this License.  For example, you may
 | 
				
			||||||
 | 
					not impose a license fee, royalty, or other charge for exercise of
 | 
				
			||||||
 | 
					rights granted under this License, and you may not initiate litigation
 | 
				
			||||||
 | 
					(including a cross-claim or counterclaim in a lawsuit) alleging that
 | 
				
			||||||
 | 
					any patent claim is infringed by making, using, selling, offering for
 | 
				
			||||||
 | 
					sale, or importing the Program or any portion of it.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  11. Patents.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  A "contributor" is a copyright holder who authorizes use under this
 | 
				
			||||||
 | 
					License of the Program or a work on which the Program is based.  The
 | 
				
			||||||
 | 
					work thus licensed is called the contributor's "contributor version".
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  A contributor's "essential patent claims" are all patent claims
 | 
				
			||||||
 | 
					owned or controlled by the contributor, whether already acquired or
 | 
				
			||||||
 | 
					hereafter acquired, that would be infringed by some manner, permitted
 | 
				
			||||||
 | 
					by this License, of making, using, or selling its contributor version,
 | 
				
			||||||
 | 
					but do not include claims that would be infringed only as a
 | 
				
			||||||
 | 
					consequence of further modification of the contributor version.  For
 | 
				
			||||||
 | 
					purposes of this definition, "control" includes the right to grant
 | 
				
			||||||
 | 
					patent sublicenses in a manner consistent with the requirements of
 | 
				
			||||||
 | 
					this License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Each contributor grants you a non-exclusive, worldwide, royalty-free
 | 
				
			||||||
 | 
					patent license under the contributor's essential patent claims, to
 | 
				
			||||||
 | 
					make, use, sell, offer for sale, import and otherwise run, modify and
 | 
				
			||||||
 | 
					propagate the contents of its contributor version.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  In the following three paragraphs, a "patent license" is any express
 | 
				
			||||||
 | 
					agreement or commitment, however denominated, not to enforce a patent
 | 
				
			||||||
 | 
					(such as an express permission to practice a patent or covenant not to
 | 
				
			||||||
 | 
					sue for patent infringement).  To "grant" such a patent license to a
 | 
				
			||||||
 | 
					party means to make such an agreement or commitment not to enforce a
 | 
				
			||||||
 | 
					patent against the party.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  If you convey a covered work, knowingly relying on a patent license,
 | 
				
			||||||
 | 
					and the Corresponding Source of the work is not available for anyone
 | 
				
			||||||
 | 
					to copy, free of charge and under the terms of this License, through a
 | 
				
			||||||
 | 
					publicly available network server or other readily accessible means,
 | 
				
			||||||
 | 
					then you must either (1) cause the Corresponding Source to be so
 | 
				
			||||||
 | 
					available, or (2) arrange to deprive yourself of the benefit of the
 | 
				
			||||||
 | 
					patent license for this particular work, or (3) arrange, in a manner
 | 
				
			||||||
 | 
					consistent with the requirements of this License, to extend the patent
 | 
				
			||||||
 | 
					license to downstream recipients.  "Knowingly relying" means you have
 | 
				
			||||||
 | 
					actual knowledge that, but for the patent license, your conveying the
 | 
				
			||||||
 | 
					covered work in a country, or your recipient's use of the covered work
 | 
				
			||||||
 | 
					in a country, would infringe one or more identifiable patents in that
 | 
				
			||||||
 | 
					country that you have reason to believe are valid.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  If, pursuant to or in connection with a single transaction or
 | 
				
			||||||
 | 
					arrangement, you convey, or propagate by procuring conveyance of, a
 | 
				
			||||||
 | 
					covered work, and grant a patent license to some of the parties
 | 
				
			||||||
 | 
					receiving the covered work authorizing them to use, propagate, modify
 | 
				
			||||||
 | 
					or convey a specific copy of the covered work, then the patent license
 | 
				
			||||||
 | 
					you grant is automatically extended to all recipients of the covered
 | 
				
			||||||
 | 
					work and works based on it.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  A patent license is "discriminatory" if it does not include within
 | 
				
			||||||
 | 
					the scope of its coverage, prohibits the exercise of, or is
 | 
				
			||||||
 | 
					conditioned on the non-exercise of one or more of the rights that are
 | 
				
			||||||
 | 
					specifically granted under this License.  You may not convey a covered
 | 
				
			||||||
 | 
					work if you are a party to an arrangement with a third party that is
 | 
				
			||||||
 | 
					in the business of distributing software, under which you make payment
 | 
				
			||||||
 | 
					to the third party based on the extent of your activity of conveying
 | 
				
			||||||
 | 
					the work, and under which the third party grants, to any of the
 | 
				
			||||||
 | 
					parties who would receive the covered work from you, a discriminatory
 | 
				
			||||||
 | 
					patent license (a) in connection with copies of the covered work
 | 
				
			||||||
 | 
					conveyed by you (or copies made from those copies), or (b) primarily
 | 
				
			||||||
 | 
					for and in connection with specific products or compilations that
 | 
				
			||||||
 | 
					contain the covered work, unless you entered into that arrangement,
 | 
				
			||||||
 | 
					or that patent license was granted, prior to 28 March 2007.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Nothing in this License shall be construed as excluding or limiting
 | 
				
			||||||
 | 
					any implied license or other defenses to infringement that may
 | 
				
			||||||
 | 
					otherwise be available to you under applicable patent law.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  12. No Surrender of Others' Freedom.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  If conditions are imposed on you (whether by court order, agreement or
 | 
				
			||||||
 | 
					otherwise) that contradict the conditions of this License, they do not
 | 
				
			||||||
 | 
					excuse you from the conditions of this License.  If you cannot convey a
 | 
				
			||||||
 | 
					covered work so as to satisfy simultaneously your obligations under this
 | 
				
			||||||
 | 
					License and any other pertinent obligations, then as a consequence you may
 | 
				
			||||||
 | 
					not convey it at all.  For example, if you agree to terms that obligate you
 | 
				
			||||||
 | 
					to collect a royalty for further conveying from those to whom you convey
 | 
				
			||||||
 | 
					the Program, the only way you could satisfy both those terms and this
 | 
				
			||||||
 | 
					License would be to refrain entirely from conveying the Program.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  13. Use with the GNU Affero General Public License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Notwithstanding any other provision of this License, you have
 | 
				
			||||||
 | 
					permission to link or combine any covered work with a work licensed
 | 
				
			||||||
 | 
					under version 3 of the GNU Affero General Public License into a single
 | 
				
			||||||
 | 
					combined work, and to convey the resulting work.  The terms of this
 | 
				
			||||||
 | 
					License will continue to apply to the part which is the covered work,
 | 
				
			||||||
 | 
					but the special requirements of the GNU Affero General Public License,
 | 
				
			||||||
 | 
					section 13, concerning interaction through a network will apply to the
 | 
				
			||||||
 | 
					combination as such.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  14. Revised Versions of this License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  The Free Software Foundation may publish revised and/or new versions of
 | 
				
			||||||
 | 
					the GNU General Public License from time to time.  Such new versions will
 | 
				
			||||||
 | 
					be similar in spirit to the present version, but may differ in detail to
 | 
				
			||||||
 | 
					address new problems or concerns.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Each version is given a distinguishing version number.  If the
 | 
				
			||||||
 | 
					Program specifies that a certain numbered version of the GNU General
 | 
				
			||||||
 | 
					Public License "or any later version" applies to it, you have the
 | 
				
			||||||
 | 
					option of following the terms and conditions either of that numbered
 | 
				
			||||||
 | 
					version or of any later version published by the Free Software
 | 
				
			||||||
 | 
					Foundation.  If the Program does not specify a version number of the
 | 
				
			||||||
 | 
					GNU General Public License, you may choose any version ever published
 | 
				
			||||||
 | 
					by the Free Software Foundation.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  If the Program specifies that a proxy can decide which future
 | 
				
			||||||
 | 
					versions of the GNU General Public License can be used, that proxy's
 | 
				
			||||||
 | 
					public statement of acceptance of a version permanently authorizes you
 | 
				
			||||||
 | 
					to choose that version for the Program.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Later license versions may give you additional or different
 | 
				
			||||||
 | 
					permissions.  However, no additional obligations are imposed on any
 | 
				
			||||||
 | 
					author or copyright holder as a result of your choosing to follow a
 | 
				
			||||||
 | 
					later version.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  15. Disclaimer of Warranty.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
 | 
				
			||||||
 | 
					APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
 | 
				
			||||||
 | 
					HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
 | 
				
			||||||
 | 
					OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
 | 
				
			||||||
 | 
					THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 | 
				
			||||||
 | 
					PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
 | 
				
			||||||
 | 
					IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
 | 
				
			||||||
 | 
					ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  16. Limitation of Liability.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
 | 
				
			||||||
 | 
					WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
 | 
				
			||||||
 | 
					THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
 | 
				
			||||||
 | 
					GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
 | 
				
			||||||
 | 
					USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
 | 
				
			||||||
 | 
					DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
 | 
				
			||||||
 | 
					PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
 | 
				
			||||||
 | 
					EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
 | 
				
			||||||
 | 
					SUCH DAMAGES.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  17. Interpretation of Sections 15 and 16.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  If the disclaimer of warranty and limitation of liability provided
 | 
				
			||||||
 | 
					above cannot be given local legal effect according to their terms,
 | 
				
			||||||
 | 
					reviewing courts shall apply local law that most closely approximates
 | 
				
			||||||
 | 
					an absolute waiver of all civil liability in connection with the
 | 
				
			||||||
 | 
					Program, unless a warranty or assumption of liability accompanies a
 | 
				
			||||||
 | 
					copy of the Program in return for a fee.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                     END OF TERMS AND CONDITIONS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            How to Apply These Terms to Your New Programs
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  If you develop a new program, and you want it to be of the greatest
 | 
				
			||||||
 | 
					possible use to the public, the best way to achieve this is to make it
 | 
				
			||||||
 | 
					free software which everyone can redistribute and change under these terms.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  To do so, attach the following notices to the program.  It is safest
 | 
				
			||||||
 | 
					to attach them to the start of each source file to most effectively
 | 
				
			||||||
 | 
					state the exclusion of warranty; and each file should have at least
 | 
				
			||||||
 | 
					the "copyright" line and a pointer to where the full notice is found.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <one line to give the program's name and a brief idea of what it does.>
 | 
				
			||||||
 | 
					    Copyright (C) <year>  <name of author>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    This program is free software: you can redistribute it and/or modify
 | 
				
			||||||
 | 
					    it under the terms of the GNU General Public License as published by
 | 
				
			||||||
 | 
					    the Free Software Foundation, either version 3 of the License, or
 | 
				
			||||||
 | 
					    (at your option) any later version.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					    but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
				
			||||||
 | 
					    GNU General Public License for more details.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					    along with this program.  If not, see <https://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Also add information on how to contact you by electronic and paper mail.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  If the program does terminal interaction, make it output a short
 | 
				
			||||||
 | 
					notice like this when it starts in an interactive mode:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <program>  Copyright (C) <year>  <name of author>
 | 
				
			||||||
 | 
					    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
 | 
				
			||||||
 | 
					    This is free software, and you are welcome to redistribute it
 | 
				
			||||||
 | 
					    under certain conditions; type `show c' for details.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The hypothetical commands `show w' and `show c' should show the appropriate
 | 
				
			||||||
 | 
					parts of the General Public License.  Of course, your program's commands
 | 
				
			||||||
 | 
					might be different; for a GUI interface, you would use an "about box".
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  You should also get your employer (if you work as a programmer) or school,
 | 
				
			||||||
 | 
					if any, to sign a "copyright disclaimer" for the program, if necessary.
 | 
				
			||||||
 | 
					For more information on this, and how to apply and follow the GNU GPL, see
 | 
				
			||||||
 | 
					<https://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  The GNU General Public License does not permit incorporating your program
 | 
				
			||||||
 | 
					into proprietary programs.  If your program is a subroutine library, you
 | 
				
			||||||
 | 
					may consider it more useful to permit linking proprietary applications with
 | 
				
			||||||
 | 
					the library.  If this is what you want to do, use the GNU Lesser General
 | 
				
			||||||
 | 
					Public License instead of this License.  But first, please read
 | 
				
			||||||
 | 
					<https://www.gnu.org/licenses/why-not-lgpl.html>.
 | 
				
			||||||
							
								
								
									
										28
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,28 @@
 | 
				
			|||||||
 | 
					# network
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Overview
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Website and documentation source for the Dead Network project.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Development & Building
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					nodejs is required in your dev. environment. The method for installing nodejs depends on your operating system. This software is built using [Docusaurus](https://docusaurus.io).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Go to the root directory of your repository and install dependencies:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```shell
 | 
				
			||||||
 | 
					pnpm install
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Build the project with the following command
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```shell
 | 
				
			||||||
 | 
					pnpm build
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Start a local dev. instance with the following command
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```shell
 | 
				
			||||||
 | 
					pnpm start
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
							
								
								
									
										119
									
								
								config.toml
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,119 @@
 | 
				
			|||||||
 | 
					[general]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#### Address & Root dir
 | 
				
			||||||
 | 
					host = "::"
 | 
				
			||||||
 | 
					port = 80
 | 
				
			||||||
 | 
					root = "/app"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#### Logging
 | 
				
			||||||
 | 
					log-level = "error"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#### Cache Control headers
 | 
				
			||||||
 | 
					cache-control-headers = true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#### Auto Compression
 | 
				
			||||||
 | 
					compression = true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#### Error pages
 | 
				
			||||||
 | 
					page404 = "/app/404.html"
 | 
				
			||||||
 | 
					page50x = "/app/404.html"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#### HTTP/2 + TLS
 | 
				
			||||||
 | 
					http2 = false
 | 
				
			||||||
 | 
					http2-tls-cert = ""
 | 
				
			||||||
 | 
					http2-tls-key = ""
 | 
				
			||||||
 | 
					https-redirect = false
 | 
				
			||||||
 | 
					https-redirect-host = "localhost"
 | 
				
			||||||
 | 
					https-redirect-from-port = 80
 | 
				
			||||||
 | 
					https-redirect-from-hosts = "localhost"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#### CORS & Security headers
 | 
				
			||||||
 | 
					# security-headers = true
 | 
				
			||||||
 | 
					# cors-allow-origins = ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#### Directory listing
 | 
				
			||||||
 | 
					directory-listing = false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#### Directory listing sorting code
 | 
				
			||||||
 | 
					directory-listing-order = 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#### Directory listing content format
 | 
				
			||||||
 | 
					directory-listing-format = "html"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#### Basic Authentication
 | 
				
			||||||
 | 
					# basic-auth = ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#### File descriptor binding
 | 
				
			||||||
 | 
					# fd = ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#### Worker threads
 | 
				
			||||||
 | 
					threads-multiplier = 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#### Grace period after a graceful shutdown
 | 
				
			||||||
 | 
					grace-period = 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#### Page fallback for 404s
 | 
				
			||||||
 | 
					# page-fallback = ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#### Log request Remote Address if available
 | 
				
			||||||
 | 
					log-remote-address = false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#### Redirect to trailing slash in the requested directory uri
 | 
				
			||||||
 | 
					redirect-trailing-slash = true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#### Check for existing pre-compressed files
 | 
				
			||||||
 | 
					compression-static = true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#### Health-check endpoint (GET or HEAD `/health`)
 | 
				
			||||||
 | 
					health = false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Windows Only
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#### Run the web server as a Windows Service
 | 
				
			||||||
 | 
					# windows-service = false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[advanced]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#### HTTP Headers customization (examples only)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#### a. Oneline version
 | 
				
			||||||
 | 
					# [[advanced.headers]]
 | 
				
			||||||
 | 
					# source = "**/*.{js,css}"
 | 
				
			||||||
 | 
					# headers = { Access-Control-Allow-Origin = "*" }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#### b. Multiline version
 | 
				
			||||||
 | 
					# [[advanced.headers]]
 | 
				
			||||||
 | 
					# source = "/index.html"
 | 
				
			||||||
 | 
					# [advanced.headers.headers]
 | 
				
			||||||
 | 
					# Cache-Control = "public, max-age=36000"
 | 
				
			||||||
 | 
					# Content-Security-Policy = "frame-ancestors 'self'"
 | 
				
			||||||
 | 
					# Strict-Transport-Security = "max-age=63072000; includeSubDomains; preload"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#### c. Multiline version with explicit key (dotted)
 | 
				
			||||||
 | 
					# [[advanced.headers]]
 | 
				
			||||||
 | 
					# source = "**/*.{jpg,jpeg,png,ico,gif}"
 | 
				
			||||||
 | 
					# headers.Strict-Transport-Security = "max-age=63072000; includeSubDomains; preload"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### URL Redirects (examples only)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# [[advanced.redirects]]
 | 
				
			||||||
 | 
					# source = "**/*.{jpg,jpeg}"
 | 
				
			||||||
 | 
					# destination = "/images/generic1.png"
 | 
				
			||||||
 | 
					# kind = 301
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# [[advanced.redirects]]
 | 
				
			||||||
 | 
					# source = "/index.html"
 | 
				
			||||||
 | 
					# destination = "https://static-web-server.net"
 | 
				
			||||||
 | 
					# kind = 302
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### URL Rewrites (examples only)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# [[advanced.rewrites]]
 | 
				
			||||||
 | 
					# source = "**/*.{png,ico,gif}"
 | 
				
			||||||
 | 
					# destination = "/assets/favicon.ico"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# [[advanced.rewrites]]
 | 
				
			||||||
 | 
					# source = "**/*.{jpg,jpeg}"
 | 
				
			||||||
 | 
					# destination = "/images/sws.png"
 | 
				
			||||||
							
								
								
									
										22
									
								
								docker-compose.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,22 @@
 | 
				
			|||||||
 | 
					version: "3.9"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					services:
 | 
				
			||||||
 | 
					    dead_net:
 | 
				
			||||||
 | 
					        image: joseluisq/static-web-server:2
 | 
				
			||||||
 | 
					        restart: always
 | 
				
			||||||
 | 
					        environment:
 | 
				
			||||||
 | 
					          # Note: those envs are customizable but also optional
 | 
				
			||||||
 | 
					          - SERVER_HOST=127.0.0.1
 | 
				
			||||||
 | 
					          - SERVER_PORT=80
 | 
				
			||||||
 | 
					          - SERVER_ROOT=/app
 | 
				
			||||||
 | 
					        volumes:
 | 
				
			||||||
 | 
					          - ./build:/app
 | 
				
			||||||
 | 
					        networks:
 | 
				
			||||||
 | 
					          - caddy
 | 
				
			||||||
 | 
					        labels:
 | 
				
			||||||
 | 
					          caddy.address: "https://network.dead.guru"
 | 
				
			||||||
 | 
					          caddy.tls: "assada.ua@gmail.com"
 | 
				
			||||||
 | 
					networks:
 | 
				
			||||||
 | 
					  caddy:
 | 
				
			||||||
 | 
					    external:
 | 
				
			||||||
 | 
					      name: assada-services
 | 
				
			||||||
							
								
								
									
										7
									
								
								docs/about/_category_.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,7 @@
 | 
				
			|||||||
 | 
					position: 1 # float position is supported
 | 
				
			||||||
 | 
					label: About
 | 
				
			||||||
 | 
					collapsible: true # make the category collapsible
 | 
				
			||||||
 | 
					link:
 | 
				
			||||||
 | 
					  type: generated-index
 | 
				
			||||||
 | 
					  title: About Dead Network
 | 
				
			||||||
 | 
					  slug: /about
 | 
				
			||||||
							
								
								
									
										10
									
								
								docs/about/faq.mdx
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,10 @@
 | 
				
			|||||||
 | 
					---
 | 
				
			||||||
 | 
					id: faq
 | 
				
			||||||
 | 
					title: FAQs
 | 
				
			||||||
 | 
					slug: /faq
 | 
				
			||||||
 | 
					sidebar_position: 3
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## TBA
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					...
 | 
				
			||||||
							
								
								
									
										8
									
								
								docs/about/introduction.mdx
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,8 @@
 | 
				
			|||||||
 | 
					---
 | 
				
			||||||
 | 
					title: Introduction
 | 
				
			||||||
 | 
					sidebar_label: Introduction
 | 
				
			||||||
 | 
					slug: /introduction
 | 
				
			||||||
 | 
					sidebar_position: 1
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## TBA
 | 
				
			||||||
							
								
								
									
										8
									
								
								docs/about/overview/index.mdx
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,8 @@
 | 
				
			|||||||
 | 
					---
 | 
				
			||||||
 | 
					title: Overview
 | 
				
			||||||
 | 
					sidebar_label: Overview
 | 
				
			||||||
 | 
					slug: /overview
 | 
				
			||||||
 | 
					sidebar_position: 2
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## TBA
 | 
				
			||||||
							
								
								
									
										22
									
								
								docs/blocks/_lora-regions.mdx
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,22 @@
 | 
				
			|||||||
 | 
					| Region Code |       Description       |
 | 
				
			||||||
 | 
					| :---------: | :---------------------: |
 | 
				
			||||||
 | 
					|   `UNSET`   |          Unset          |
 | 
				
			||||||
 | 
					|    `US`     |      United States      |
 | 
				
			||||||
 | 
					|  `EU_433`   |  European Union 433MHz  |
 | 
				
			||||||
 | 
					|  `EU_868`   |  European Union 868MHz  |
 | 
				
			||||||
 | 
					|    `CN`     |          China          |
 | 
				
			||||||
 | 
					|    `JP`     |          Japan          |
 | 
				
			||||||
 | 
					|    `ANZ`    | Australia & New Zealand |
 | 
				
			||||||
 | 
					|    `KR`     |          Korea          |
 | 
				
			||||||
 | 
					|    `TW`     |         Taiwan          |
 | 
				
			||||||
 | 
					|    `RU`     |         Russia          |
 | 
				
			||||||
 | 
					|    `IN`     |          India          |
 | 
				
			||||||
 | 
					|  `NZ_865`   |   New Zealand 865MHz    |
 | 
				
			||||||
 | 
					|  `UA_433`   |     Ukraine 433MHz      |
 | 
				
			||||||
 | 
					|  `UA_868`   |     Ukraine 868MHz      |
 | 
				
			||||||
 | 
					|    `TH`     |        Thailand         |
 | 
				
			||||||
 | 
					|  `LORA_24`  | 2.4 GHz band worldwide  |
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					:::info
 | 
				
			||||||
 | 
					EU_433 and EU_868 have to adhere to an hourly duty cycle limitation of 10%. Your device will stop transmitting if you reach it, until it is allowed again.
 | 
				
			||||||
 | 
					:::
 | 
				
			||||||
							
								
								
									
										9
									
								
								docs/getting-started/index.mdx
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,9 @@
 | 
				
			|||||||
 | 
					---
 | 
				
			||||||
 | 
					id: getting-started
 | 
				
			||||||
 | 
					title: Getting Started
 | 
				
			||||||
 | 
					sidebar_label: Getting Started
 | 
				
			||||||
 | 
					slug: /getting-started
 | 
				
			||||||
 | 
					sidebar_position: 2
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## TBA
 | 
				
			||||||
							
								
								
									
										8
									
								
								docs/legal/index.mdx
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,8 @@
 | 
				
			|||||||
 | 
					---
 | 
				
			||||||
 | 
					title: Legal
 | 
				
			||||||
 | 
					sidebar_label: Legal
 | 
				
			||||||
 | 
					slug: /legal
 | 
				
			||||||
 | 
					sidebar_position: 9
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## TBA
 | 
				
			||||||
							
								
								
									
										7
									
								
								docs/legal/licensing.mdx
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,7 @@
 | 
				
			|||||||
 | 
					---
 | 
				
			||||||
 | 
					id: licensing
 | 
				
			||||||
 | 
					title: Licensing & Commercial Projects Usage
 | 
				
			||||||
 | 
					sidebar_label: Licensing
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## TBA
 | 
				
			||||||
							
								
								
									
										8
									
								
								docs/legal/privacy.mdx
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,8 @@
 | 
				
			|||||||
 | 
					---
 | 
				
			||||||
 | 
					id: privacy
 | 
				
			||||||
 | 
					title: Dead privacy policy
 | 
				
			||||||
 | 
					sidebar_label: Privacy
 | 
				
			||||||
 | 
					custom_edit_url: null
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## TBA
 | 
				
			||||||
							
								
								
									
										7
									
								
								docs/software/_category_.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,7 @@
 | 
				
			|||||||
 | 
					label: Software
 | 
				
			||||||
 | 
					collapsible: true
 | 
				
			||||||
 | 
					position: 6
 | 
				
			||||||
 | 
					link:
 | 
				
			||||||
 | 
					  type: generated-index
 | 
				
			||||||
 | 
					  title: Software
 | 
				
			||||||
 | 
					  slug: /software
 | 
				
			||||||
							
								
								
									
										129
									
								
								docusaurus.config.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,129 @@
 | 
				
			|||||||
 | 
					// @ts-check
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					require("dotenv").config();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @type {import('@docusaurus/types').Config} */
 | 
				
			||||||
 | 
					const config = {
 | 
				
			||||||
 | 
						title: "Dead Network",
 | 
				
			||||||
 | 
						tagline:
 | 
				
			||||||
 | 
							"Мережа сервісів і платформ, які дають змогу окремим особам і спільнотам спілкуватися, ділитися та розвиватися разом.",
 | 
				
			||||||
 | 
						url: "https://dead.guru",
 | 
				
			||||||
 | 
						baseUrl: "/",
 | 
				
			||||||
 | 
						onBrokenLinks: "throw",
 | 
				
			||||||
 | 
						onBrokenMarkdownLinks: "warn",
 | 
				
			||||||
 | 
						favicon: "design/web/favicon.ico",
 | 
				
			||||||
 | 
						organizationName: "dead",
 | 
				
			||||||
 | 
						projectName: "dead",
 | 
				
			||||||
 | 
						themeConfig: /** @type {import('@docusaurus/preset-classic').ThemeConfig} */ {
 | 
				
			||||||
 | 
							announcementBar: {
 | 
				
			||||||
 | 
								id: "2_0",
 | 
				
			||||||
 | 
								content:
 | 
				
			||||||
 | 
									'🎉 Зя`вився XMPP сервер доєднатися можна <a href="/doc/xmpp">тут</a> 🎉',
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							docs: {
 | 
				
			||||||
 | 
								sidebar: {
 | 
				
			||||||
 | 
									autoCollapseCategories: true,
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							navbar: {
 | 
				
			||||||
 | 
								title: "Dead Network",
 | 
				
			||||||
 | 
								hideOnScroll: true,
 | 
				
			||||||
 | 
								logo: {
 | 
				
			||||||
 | 
									alt: "Dead Logo",
 | 
				
			||||||
 | 
									src: "img/logo.svg",
 | 
				
			||||||
 | 
									srcDark: "img/logo-white.svg",
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								items: [
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										label: "Документація",
 | 
				
			||||||
 | 
										to: "docs/introduction",
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										label: "Клієнти",
 | 
				
			||||||
 | 
										to: "downloads",
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										label: "Інформація",
 | 
				
			||||||
 | 
										position: "right",
 | 
				
			||||||
 | 
										items: [
 | 
				
			||||||
 | 
											{
 | 
				
			||||||
 | 
												label: "Вступ",
 | 
				
			||||||
 | 
												to: "docs/introduction",
 | 
				
			||||||
 | 
											},
 | 
				
			||||||
 | 
											{
 | 
				
			||||||
 | 
												label: "Як почати",
 | 
				
			||||||
 | 
												to: "docs/getting-started",
 | 
				
			||||||
 | 
											},
 | 
				
			||||||
 | 
											{
 | 
				
			||||||
 | 
												label: "ЗІВі",
 | 
				
			||||||
 | 
												to: "docs/faq",
 | 
				
			||||||
 | 
											},
 | 
				
			||||||
 | 
										],
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										href: "https://git.dead.guru/DeadGuru/network",
 | 
				
			||||||
 | 
										position: "right",
 | 
				
			||||||
 | 
										className: "header-github-link",
 | 
				
			||||||
 | 
										"aria-label": "GitHub Репозиторій",
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								],
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							footer: {
 | 
				
			||||||
 | 
								copyright: `<a href="https://vercel.com/?utm_source=meshtastic&utm_campaign=oss">Powered by ▲ Vercel</a>.`,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							colorMode: {
 | 
				
			||||||
 | 
								respectPrefersColorScheme: true,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							mermaid: {
 | 
				
			||||||
 | 
								theme: { light: "base", dark: "base" },
 | 
				
			||||||
 | 
								options: {
 | 
				
			||||||
 | 
									themeVariables: {
 | 
				
			||||||
 | 
										primaryColor: "#f03131",
 | 
				
			||||||
 | 
										primaryTextColor: "var(--tw-prose-headings)",
 | 
				
			||||||
 | 
										primaryBorderColor: "#4D4D4D",
 | 
				
			||||||
 | 
										lineColor: "#EAD667",
 | 
				
			||||||
 | 
										secondaryColor: "#EA67BD",
 | 
				
			||||||
 | 
										tertiaryColor: "#677CEA",
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						plugins: [
 | 
				
			||||||
 | 
							() => {
 | 
				
			||||||
 | 
								return {
 | 
				
			||||||
 | 
									name: "docusaurus-tailwindcss",
 | 
				
			||||||
 | 
									configurePostCss(postcssOptions) {
 | 
				
			||||||
 | 
										postcssOptions.plugins.push(require("tailwindcss"));
 | 
				
			||||||
 | 
										postcssOptions.plugins.push(require("autoprefixer"));
 | 
				
			||||||
 | 
										return postcssOptions;
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								};
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						],
 | 
				
			||||||
 | 
						presets: [
 | 
				
			||||||
 | 
							[
 | 
				
			||||||
 | 
								"@docusaurus/preset-classic",
 | 
				
			||||||
 | 
								/** @type {import('@docusaurus/preset-classic').Options} */
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									docs: {
 | 
				
			||||||
 | 
										sidebarPath: require.resolve("./sidebars.js"),
 | 
				
			||||||
 | 
										editUrl: "https://github.com/dead/dead/edit/master/",
 | 
				
			||||||
 | 
										breadcrumbs: false,
 | 
				
			||||||
 | 
										showLastUpdateAuthor: true,
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
									theme: {
 | 
				
			||||||
 | 
										customCss: require.resolve("./src/css/custom.css"),
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							],
 | 
				
			||||||
 | 
						],
 | 
				
			||||||
 | 
						customFields: {
 | 
				
			||||||
 | 
							API_URL: process.env.API_URL,
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						markdown: {
 | 
				
			||||||
 | 
							mermaid: true,
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						themes: ["@docusaurus/theme-mermaid"],
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module.exports = config;
 | 
				
			||||||
							
								
								
									
										49
									
								
								package.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,49 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					  "name": "dead",
 | 
				
			||||||
 | 
					  "version": "0.0.0",
 | 
				
			||||||
 | 
					  "private": true,
 | 
				
			||||||
 | 
					  "license": "GPL-3.0-only",
 | 
				
			||||||
 | 
					  "scripts": {
 | 
				
			||||||
 | 
					    "docusaurus": "docusaurus",
 | 
				
			||||||
 | 
					    "start": "docusaurus start",
 | 
				
			||||||
 | 
					    "build": "docusaurus build",
 | 
				
			||||||
 | 
					    "swizzle": "docusaurus swizzle",
 | 
				
			||||||
 | 
					    "serve": "docusaurus serve",
 | 
				
			||||||
 | 
					    "clear": "docusaurus clear"
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  "dependencies": {
 | 
				
			||||||
 | 
					    "@algolia/client-search": "^4.17.0",
 | 
				
			||||||
 | 
					    "@docusaurus/core": "2.4.1",
 | 
				
			||||||
 | 
					    "@docusaurus/plugin-content-docs": "2.4.1",
 | 
				
			||||||
 | 
					    "@docusaurus/preset-classic": "2.4.1",
 | 
				
			||||||
 | 
					    "@docusaurus/theme-common": "^2.4.1",
 | 
				
			||||||
 | 
					    "@docusaurus/theme-mermaid": "^2.4.1",
 | 
				
			||||||
 | 
					    "@headlessui/react": "^1.7.14",
 | 
				
			||||||
 | 
					    "@heroicons/react": "^2.0.18",
 | 
				
			||||||
 | 
					    "@mdx-js/react": "^1.6.22",
 | 
				
			||||||
 | 
					    "@meshtastic/meshtasticjs": "2.1.9-0",
 | 
				
			||||||
 | 
					    "autoprefixer": "^10.4.14",
 | 
				
			||||||
 | 
					    "base64-js": "^1.5.1",
 | 
				
			||||||
 | 
					    "dotenv": "^16.0.3",
 | 
				
			||||||
 | 
					    "framer-motion": "^6.5.1",
 | 
				
			||||||
 | 
					    "postcss": "^8.4.23",
 | 
				
			||||||
 | 
					    "react": "^17.0.2",
 | 
				
			||||||
 | 
					    "react-dom": "^17.0.2",
 | 
				
			||||||
 | 
					    "react-icons": "^4.8.0",
 | 
				
			||||||
 | 
					    "react-responsive-carousel": "^3.2.23",
 | 
				
			||||||
 | 
					    "swr": "^2.1.5",
 | 
				
			||||||
 | 
					    "tailwindcss": "^3.3.2",
 | 
				
			||||||
 | 
					    "url-search-params-polyfill": "^8.1.1",
 | 
				
			||||||
 | 
					    "use-breakpoint": "^3.0.7"
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  "devDependencies": {
 | 
				
			||||||
 | 
					    "@docusaurus/module-type-aliases": "2.4.1",
 | 
				
			||||||
 | 
					    "@tailwindcss/typography": "^0.5.9",
 | 
				
			||||||
 | 
					    "@tsconfig/docusaurus": "^1.0.7",
 | 
				
			||||||
 | 
					    "@types/node": "^20.1.7",
 | 
				
			||||||
 | 
					    "@types/react": "^18.2.6",
 | 
				
			||||||
 | 
					    "@types/react-dom": "^18.2.4",
 | 
				
			||||||
 | 
					    "rome": "^12.1.0",
 | 
				
			||||||
 | 
					    "typescript": "^5.0.4"
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										9319
									
								
								pnpm-lock.yaml
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										11
									
								
								sidebars.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,11 @@
 | 
				
			|||||||
 | 
					// @ts-check
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */
 | 
				
			||||||
 | 
					module.exports = {
 | 
				
			||||||
 | 
						Sidebar: [
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								type: "autogenerated",
 | 
				
			||||||
 | 
								dirName: ".",
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						],
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
							
								
								
									
										27
									
								
								src/components/BatteryCalculator.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,27 @@
 | 
				
			|||||||
 | 
					import React from "react";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const BatteryCalculator = (): JSX.Element => {
 | 
				
			||||||
 | 
						return (
 | 
				
			||||||
 | 
							<div className="card">
 | 
				
			||||||
 | 
								<div className="card__header">
 | 
				
			||||||
 | 
									<h3>Battery Calculator</h3>
 | 
				
			||||||
 | 
								</div>
 | 
				
			||||||
 | 
								<div className="card__body" style={{ display: "flex", gap: "2rem" }}>
 | 
				
			||||||
 | 
									<div>
 | 
				
			||||||
 | 
										<input placeholder="Search" />
 | 
				
			||||||
 | 
										<input placeholder="Search" />
 | 
				
			||||||
 | 
										<input placeholder="Search" />
 | 
				
			||||||
 | 
										<input placeholder="Search" />
 | 
				
			||||||
 | 
									</div>
 | 
				
			||||||
 | 
								</div>
 | 
				
			||||||
 | 
								<div className="card__footer">
 | 
				
			||||||
 | 
									<button
 | 
				
			||||||
 | 
										type="button"
 | 
				
			||||||
 | 
										className="button button--secondary button--block"
 | 
				
			||||||
 | 
									>
 | 
				
			||||||
 | 
										See All
 | 
				
			||||||
 | 
									</button>
 | 
				
			||||||
 | 
								</div>
 | 
				
			||||||
 | 
							</div>
 | 
				
			||||||
 | 
						);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
							
								
								
									
										16
									
								
								src/components/Button.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,16 @@
 | 
				
			|||||||
 | 
					import React from "react";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { HTMLMotionProps, motion } from "framer-motion";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const Button = ({ children, ...props }: HTMLMotionProps<"div">) => {
 | 
				
			||||||
 | 
						return (
 | 
				
			||||||
 | 
							<motion.div
 | 
				
			||||||
 | 
								{...props}
 | 
				
			||||||
 | 
								whileHover={{ scale: 1.1, backgroundColor: "var(--tertiary)" }}
 | 
				
			||||||
 | 
								whileTap={{ scale: 1.0 }}
 | 
				
			||||||
 | 
								className="m-auto flex cursor-pointer rounded-full bg-secondary p-3 shadow-md"
 | 
				
			||||||
 | 
							>
 | 
				
			||||||
 | 
								<div className="m-auto">{children}</div>
 | 
				
			||||||
 | 
							</motion.div>
 | 
				
			||||||
 | 
						);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
							
								
								
									
										13
									
								
								src/components/ColorMode.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,13 @@
 | 
				
			|||||||
 | 
					import React from "react";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export interface ColorModeProps {
 | 
				
			||||||
 | 
						children: React.ReactNode;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const Dark = ({ children }: ColorModeProps): JSX.Element => {
 | 
				
			||||||
 | 
						return <div className="hideLight">{children}</div>;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const Light = ({ children }: ColorModeProps): JSX.Element => {
 | 
				
			||||||
 | 
						return <div className="hideDark">{children}</div>;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
							
								
								
									
										274
									
								
								src/components/HardwareComponents.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,274 @@
 | 
				
			|||||||
 | 
					// import React from 'react';
 | 
				
			||||||
 | 
					// import data from '/docs/hardware/supported/devices.json'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// function checkVersionOverrides(selectedDevice, version, value) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//   var versionOverride = selectedDevice.versionOverrides[version]
 | 
				
			||||||
 | 
					//   var device = selectedDevice
 | 
				
			||||||
 | 
					//   var objectSegment = value.split('.')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//   while (objectSegment.length > 1) {
 | 
				
			||||||
 | 
					//     console.log(objectSegment)
 | 
				
			||||||
 | 
					//     let test = objectSegment.shift()
 | 
				
			||||||
 | 
					//     console.log('test', test, 'og objectSegment', objectSegment)
 | 
				
			||||||
 | 
					//     versionOverride = versionOverride[test]
 | 
				
			||||||
 | 
					//     device = device[test]
 | 
				
			||||||
 | 
					//   }
 | 
				
			||||||
 | 
					//   if (versionOverride) {
 | 
				
			||||||
 | 
					//     return versionOverride
 | 
				
			||||||
 | 
					//   } else return device
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//   // if (selectedDevice.versionOverrides[version][value]) {
 | 
				
			||||||
 | 
					//   //   return selectedDevice.versionOverrides[version][value]
 | 
				
			||||||
 | 
					//   // } else {
 | 
				
			||||||
 | 
					//   //   console.log("no", selectedDevice, value, selectedDevice[value])
 | 
				
			||||||
 | 
					//   //   return selectedDevice[value]
 | 
				
			||||||
 | 
					//   // }
 | 
				
			||||||
 | 
					// }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// export const MeshtasticFeatures = ({device, version}): JSX.Element => {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//   const selectedDevice = data[device]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//   return (
 | 
				
			||||||
 | 
					//     <table>
 | 
				
			||||||
 | 
					//       <thead>
 | 
				
			||||||
 | 
					//         <th style={{align: "center"}}>
 | 
				
			||||||
 | 
					//           Meshtastic Feature
 | 
				
			||||||
 | 
					//         </th>
 | 
				
			||||||
 | 
					//         <th style={{align: "center"}}>
 | 
				
			||||||
 | 
					//           Device Support
 | 
				
			||||||
 | 
					//         </th>
 | 
				
			||||||
 | 
					//       </thead>
 | 
				
			||||||
 | 
					//       <tbody>
 | 
				
			||||||
 | 
					//         <tr>
 | 
				
			||||||
 | 
					//           <td style={{align: "center"}}>
 | 
				
			||||||
 | 
					//             Support Status
 | 
				
			||||||
 | 
					//           </td>
 | 
				
			||||||
 | 
					//           <td style={{align: "center"}}>
 | 
				
			||||||
 | 
					//             {checkVersionOverrides(selectedDevice, version, 'supportStatus')}
 | 
				
			||||||
 | 
					//           </td>
 | 
				
			||||||
 | 
					//         </tr>
 | 
				
			||||||
 | 
					//         <tr>
 | 
				
			||||||
 | 
					//           <td style={{align: "center"}}>
 | 
				
			||||||
 | 
					//             Bluetooth
 | 
				
			||||||
 | 
					//           </td>
 | 
				
			||||||
 | 
					//           <td style={{align: "center"}}>
 | 
				
			||||||
 | 
					//             {checkVersionOverrides(selectedDevice, version, "features.bluetoothCapable")}
 | 
				
			||||||
 | 
					//           </td>
 | 
				
			||||||
 | 
					//         </tr>
 | 
				
			||||||
 | 
					//         <tr>
 | 
				
			||||||
 | 
					//           <td style={{align: "center"}}>
 | 
				
			||||||
 | 
					//             Module - Canned Message
 | 
				
			||||||
 | 
					//           </td>
 | 
				
			||||||
 | 
					//           <td style={{align: "center"}}>
 | 
				
			||||||
 | 
					//           </td>
 | 
				
			||||||
 | 
					//         </tr>
 | 
				
			||||||
 | 
					//         <tr>
 | 
				
			||||||
 | 
					//           <td style={{align: "center"}}>
 | 
				
			||||||
 | 
					//             Module - External Notification
 | 
				
			||||||
 | 
					//           </td>
 | 
				
			||||||
 | 
					//           <td style={{align: "center"}}>
 | 
				
			||||||
 | 
					//             VALUE
 | 
				
			||||||
 | 
					//           </td>
 | 
				
			||||||
 | 
					//         </tr>
 | 
				
			||||||
 | 
					//         <tr>
 | 
				
			||||||
 | 
					//           <td style={{align: "center"}}>
 | 
				
			||||||
 | 
					//             Module - Range Test
 | 
				
			||||||
 | 
					//           </td>
 | 
				
			||||||
 | 
					//           <td style={{align: "center"}}>
 | 
				
			||||||
 | 
					//             VALUE
 | 
				
			||||||
 | 
					//           </td>
 | 
				
			||||||
 | 
					//         </tr>
 | 
				
			||||||
 | 
					//         <tr>
 | 
				
			||||||
 | 
					//           <td style={{align: "center"}}>
 | 
				
			||||||
 | 
					//             Module - Rotary Encoder
 | 
				
			||||||
 | 
					//           </td>
 | 
				
			||||||
 | 
					//           <td style={{align: "center"}}>
 | 
				
			||||||
 | 
					//             VALUE
 | 
				
			||||||
 | 
					//           </td>
 | 
				
			||||||
 | 
					//         </tr>
 | 
				
			||||||
 | 
					//         <tr>
 | 
				
			||||||
 | 
					//           <td style={{align: "center"}}>
 | 
				
			||||||
 | 
					//             Module - Store and Forward
 | 
				
			||||||
 | 
					//           </td>
 | 
				
			||||||
 | 
					//           <td style={{align: "center"}}>
 | 
				
			||||||
 | 
					//             VALUE
 | 
				
			||||||
 | 
					//           </td>
 | 
				
			||||||
 | 
					//         </tr>
 | 
				
			||||||
 | 
					//         <tr>
 | 
				
			||||||
 | 
					//           <td style={{align: "center"}}>
 | 
				
			||||||
 | 
					//             Module - Telemetry (aka Environmental Measurement)
 | 
				
			||||||
 | 
					//           </td>
 | 
				
			||||||
 | 
					//           <td style={{align: "center"}}>
 | 
				
			||||||
 | 
					//             VALUE
 | 
				
			||||||
 | 
					//           </td>
 | 
				
			||||||
 | 
					//         </tr>
 | 
				
			||||||
 | 
					//         <tr>
 | 
				
			||||||
 | 
					//           <td style={{align: "center"}}>
 | 
				
			||||||
 | 
					//             Router - Always Powered
 | 
				
			||||||
 | 
					//           </td>
 | 
				
			||||||
 | 
					//           <td style={{align: "center"}}>
 | 
				
			||||||
 | 
					//             VALUE
 | 
				
			||||||
 | 
					//           </td>
 | 
				
			||||||
 | 
					//         </tr>
 | 
				
			||||||
 | 
					//         <tr>
 | 
				
			||||||
 | 
					//           <td style={{align: "center"}}>
 | 
				
			||||||
 | 
					//             Router - Solar Powered
 | 
				
			||||||
 | 
					//           </td>
 | 
				
			||||||
 | 
					//           <td style={{align: "center"}}>
 | 
				
			||||||
 | 
					//             VALUE
 | 
				
			||||||
 | 
					//           </td>
 | 
				
			||||||
 | 
					//         </tr>
 | 
				
			||||||
 | 
					//         <tr>
 | 
				
			||||||
 | 
					//           <td style={{align: "center"}}>
 | 
				
			||||||
 | 
					//             WiFi
 | 
				
			||||||
 | 
					//           </td>
 | 
				
			||||||
 | 
					//           <td style={{align: "center"}}>
 | 
				
			||||||
 | 
					//             VALUE
 | 
				
			||||||
 | 
					//           </td>
 | 
				
			||||||
 | 
					//         </tr>
 | 
				
			||||||
 | 
					//       </tbody>
 | 
				
			||||||
 | 
					//     </table>
 | 
				
			||||||
 | 
					//   );
 | 
				
			||||||
 | 
					// };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// export const HardwareSpecifications = ({device, version}): JSX.Element => {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//   const selectedDevice = data[device]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//   return (
 | 
				
			||||||
 | 
					//     <table>
 | 
				
			||||||
 | 
					//       <thead>
 | 
				
			||||||
 | 
					//         <th style={{align: "center"}}>
 | 
				
			||||||
 | 
					//           Specification
 | 
				
			||||||
 | 
					//         </th>
 | 
				
			||||||
 | 
					//         <th style={{align: "center"}}>
 | 
				
			||||||
 | 
					//           Value
 | 
				
			||||||
 | 
					//         </th>
 | 
				
			||||||
 | 
					//       </thead>
 | 
				
			||||||
 | 
					//       <tbody>
 | 
				
			||||||
 | 
					//         <tr>
 | 
				
			||||||
 | 
					//           <td style={{align: "center"}}>
 | 
				
			||||||
 | 
					//             Bluetooth
 | 
				
			||||||
 | 
					//           </td>
 | 
				
			||||||
 | 
					//           <td style={{align: "center"}}>
 | 
				
			||||||
 | 
					//             VALUE
 | 
				
			||||||
 | 
					//           </td>
 | 
				
			||||||
 | 
					//         </tr>
 | 
				
			||||||
 | 
					//         <tr>
 | 
				
			||||||
 | 
					//           <td style={{align: "center"}}>
 | 
				
			||||||
 | 
					//             Bluetooth Antenna
 | 
				
			||||||
 | 
					//           </td>
 | 
				
			||||||
 | 
					//           <td style={{align: "center"}}>
 | 
				
			||||||
 | 
					//             VALUE
 | 
				
			||||||
 | 
					//           </td>
 | 
				
			||||||
 | 
					//         </tr>
 | 
				
			||||||
 | 
					//         <tr>
 | 
				
			||||||
 | 
					//           <td style={{align: "center"}}>
 | 
				
			||||||
 | 
					//             Chipset
 | 
				
			||||||
 | 
					//           </td>
 | 
				
			||||||
 | 
					//           <td style={{align: "center"}}>
 | 
				
			||||||
 | 
					//             VALUE
 | 
				
			||||||
 | 
					//           </td>
 | 
				
			||||||
 | 
					//         </tr>
 | 
				
			||||||
 | 
					//         <tr>
 | 
				
			||||||
 | 
					//           <td style={{align: "center"}}>
 | 
				
			||||||
 | 
					//             Driver
 | 
				
			||||||
 | 
					//           </td>
 | 
				
			||||||
 | 
					//           <td style={{align: "center"}}>
 | 
				
			||||||
 | 
					//             VALUE
 | 
				
			||||||
 | 
					//           </td>
 | 
				
			||||||
 | 
					//         </tr>
 | 
				
			||||||
 | 
					//         <tr>
 | 
				
			||||||
 | 
					//           <td style={{align: "center"}}>
 | 
				
			||||||
 | 
					//             GPS
 | 
				
			||||||
 | 
					//           </td>
 | 
				
			||||||
 | 
					//           <td style={{align: "center"}}>
 | 
				
			||||||
 | 
					//             VALUE
 | 
				
			||||||
 | 
					//           </td>
 | 
				
			||||||
 | 
					//         </tr>
 | 
				
			||||||
 | 
					//         <tr>
 | 
				
			||||||
 | 
					//           <td style={{align: "center"}}>
 | 
				
			||||||
 | 
					//             Flash
 | 
				
			||||||
 | 
					//           </td>
 | 
				
			||||||
 | 
					//           <td style={{align: "center"}}>
 | 
				
			||||||
 | 
					//             VALUE
 | 
				
			||||||
 | 
					//           </td>
 | 
				
			||||||
 | 
					//         </tr>
 | 
				
			||||||
 | 
					//         <tr>
 | 
				
			||||||
 | 
					//           <td style={{align: "center"}}>
 | 
				
			||||||
 | 
					//             Frequency - 433MHz
 | 
				
			||||||
 | 
					//           </td>
 | 
				
			||||||
 | 
					//           <td style={{align: "center"}}>
 | 
				
			||||||
 | 
					//             VALUE
 | 
				
			||||||
 | 
					//           </td>
 | 
				
			||||||
 | 
					//         </tr>
 | 
				
			||||||
 | 
					//         <tr>
 | 
				
			||||||
 | 
					//           <td style={{align: "center"}}>
 | 
				
			||||||
 | 
					//             Frequency - 868MHz
 | 
				
			||||||
 | 
					//           </td>
 | 
				
			||||||
 | 
					//           <td style={{align: "center"}}>
 | 
				
			||||||
 | 
					//             VALUE
 | 
				
			||||||
 | 
					//           </td>
 | 
				
			||||||
 | 
					//         </tr>
 | 
				
			||||||
 | 
					//         <tr>
 | 
				
			||||||
 | 
					//           <td style={{align: "center"}}>
 | 
				
			||||||
 | 
					//             Frequency - 915MHz
 | 
				
			||||||
 | 
					//           </td>
 | 
				
			||||||
 | 
					//           <td style={{align: "center"}}>
 | 
				
			||||||
 | 
					//             VALUE
 | 
				
			||||||
 | 
					//           </td>
 | 
				
			||||||
 | 
					//         </tr>
 | 
				
			||||||
 | 
					//         <tr>
 | 
				
			||||||
 | 
					//           <td style={{align: "center"}}>
 | 
				
			||||||
 | 
					//             Frequency - 923MHz
 | 
				
			||||||
 | 
					//           </td>
 | 
				
			||||||
 | 
					//           <td style={{align: "center"}}>
 | 
				
			||||||
 | 
					//             VALUE
 | 
				
			||||||
 | 
					//           </td>
 | 
				
			||||||
 | 
					//         </tr>
 | 
				
			||||||
 | 
					//         <tr>
 | 
				
			||||||
 | 
					//           <td style={{align: "center"}}>
 | 
				
			||||||
 | 
					//             LoRa Transceiver
 | 
				
			||||||
 | 
					//           </td>
 | 
				
			||||||
 | 
					//           <td style={{align: "center"}}>
 | 
				
			||||||
 | 
					//             VALUE
 | 
				
			||||||
 | 
					//           </td>
 | 
				
			||||||
 | 
					//         </tr>
 | 
				
			||||||
 | 
					//         <tr>
 | 
				
			||||||
 | 
					//           <td style={{align: "center"}}>
 | 
				
			||||||
 | 
					//             PSRAM
 | 
				
			||||||
 | 
					//           </td>
 | 
				
			||||||
 | 
					//           <td style={{align: "center"}}>
 | 
				
			||||||
 | 
					//             VALUE
 | 
				
			||||||
 | 
					//           </td>
 | 
				
			||||||
 | 
					//         </tr>
 | 
				
			||||||
 | 
					//         <tr>
 | 
				
			||||||
 | 
					//           <td style={{align: "center"}}>
 | 
				
			||||||
 | 
					//             RAM
 | 
				
			||||||
 | 
					//           </td>
 | 
				
			||||||
 | 
					//           <td style={{align: "center"}}>
 | 
				
			||||||
 | 
					//             VALUE
 | 
				
			||||||
 | 
					//           </td>
 | 
				
			||||||
 | 
					//         </tr>
 | 
				
			||||||
 | 
					//         <tr>
 | 
				
			||||||
 | 
					//           <td style={{align: "center"}}>
 | 
				
			||||||
 | 
					//             WiFi
 | 
				
			||||||
 | 
					//           </td>
 | 
				
			||||||
 | 
					//           <td style={{align: "center"}}>
 | 
				
			||||||
 | 
					//             VALUE
 | 
				
			||||||
 | 
					//           </td>
 | 
				
			||||||
 | 
					//         </tr>
 | 
				
			||||||
 | 
					//         <tr>
 | 
				
			||||||
 | 
					//           <td style={{align: "center"}}>
 | 
				
			||||||
 | 
					//             WiFi Antenna
 | 
				
			||||||
 | 
					//           </td>
 | 
				
			||||||
 | 
					//           <td style={{align: "center"}}>
 | 
				
			||||||
 | 
					//             VALUE
 | 
				
			||||||
 | 
					//           </td>
 | 
				
			||||||
 | 
					//         </tr>
 | 
				
			||||||
 | 
					//       </tbody>
 | 
				
			||||||
 | 
					//     </table>
 | 
				
			||||||
 | 
					//   );
 | 
				
			||||||
 | 
					// };
 | 
				
			||||||
							
								
								
									
										49
									
								
								src/components/Modal.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,49 @@
 | 
				
			|||||||
 | 
					import React from "react";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { AnimatePresence, motion } from "framer-motion";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { Dialog } from "@headlessui/react";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export interface ModalProps {
 | 
				
			||||||
 | 
						open: boolean;
 | 
				
			||||||
 | 
						onClose: () => void;
 | 
				
			||||||
 | 
						children: React.ReactNode;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const Modal = ({ open, onClose, children }: ModalProps): JSX.Element => {
 | 
				
			||||||
 | 
						return (
 | 
				
			||||||
 | 
							<AnimatePresence initial={false} exitBeforeEnter={true}>
 | 
				
			||||||
 | 
								<Dialog
 | 
				
			||||||
 | 
									as="div"
 | 
				
			||||||
 | 
									className="fixed inset-0 z-10 overflow-y-auto"
 | 
				
			||||||
 | 
									open={open}
 | 
				
			||||||
 | 
									onClose={onClose}
 | 
				
			||||||
 | 
								>
 | 
				
			||||||
 | 
									<div className="min-h-screen px-0.5 text-center md:px-4">
 | 
				
			||||||
 | 
										<motion.div
 | 
				
			||||||
 | 
											initial={{ opacity: 0 }}
 | 
				
			||||||
 | 
											animate={{ opacity: 1 }}
 | 
				
			||||||
 | 
											exit={{ opacity: 0 }}
 | 
				
			||||||
 | 
										>
 | 
				
			||||||
 | 
											<Dialog.Overlay className="fixed inset-0 backdrop-blur-md" />
 | 
				
			||||||
 | 
										</motion.div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										<span
 | 
				
			||||||
 | 
											className="inline-block h-screen align-middle"
 | 
				
			||||||
 | 
											aria-hidden="true"
 | 
				
			||||||
 | 
										>
 | 
				
			||||||
 | 
											​
 | 
				
			||||||
 | 
										</span>
 | 
				
			||||||
 | 
										<div className="inline-block w-full transform text-left align-middle transition-all 2xl:max-w-7xl">
 | 
				
			||||||
 | 
											<div className="group relative">
 | 
				
			||||||
 | 
												<div className="animate-tilt absolute -inset-0.5 rotate-2 rounded-lg bg-accent shadow-md transition duration-1000 group-hover:opacity-100 group-hover:duration-200" />
 | 
				
			||||||
 | 
												<div className="relative flex flex-col overflow-hidden rounded-2xl bg-base shadow-md md:aspect-[2/1] md:flex-row md:bg-primary">
 | 
				
			||||||
 | 
													{children}
 | 
				
			||||||
 | 
												</div>
 | 
				
			||||||
 | 
											</div>
 | 
				
			||||||
 | 
										</div>
 | 
				
			||||||
 | 
									</div>
 | 
				
			||||||
 | 
								</Dialog>
 | 
				
			||||||
 | 
							</AnimatePresence>
 | 
				
			||||||
 | 
						);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
							
								
								
									
										25
									
								
								src/components/PageLayout.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,25 @@
 | 
				
			|||||||
 | 
					import React from "react";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import Layout from "@theme/Layout";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export interface PageLayoutProps {
 | 
				
			||||||
 | 
						title: string;
 | 
				
			||||||
 | 
						description: string;
 | 
				
			||||||
 | 
						children: React.ReactNode;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const PageLayout = ({
 | 
				
			||||||
 | 
						title,
 | 
				
			||||||
 | 
						description,
 | 
				
			||||||
 | 
						children,
 | 
				
			||||||
 | 
					}: PageLayoutProps): JSX.Element => {
 | 
				
			||||||
 | 
						return (
 | 
				
			||||||
 | 
							<Layout title={title} description={description}>
 | 
				
			||||||
 | 
								{children}
 | 
				
			||||||
 | 
							</Layout>
 | 
				
			||||||
 | 
						);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export interface ColorModeProps {
 | 
				
			||||||
 | 
						children: React.ReactNode;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										31
									
								
								src/components/homepage/SocialCard.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,31 @@
 | 
				
			|||||||
 | 
					import React from "react";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { FiExternalLink } from "react-icons/fi";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export interface SocialCardProps {
 | 
				
			||||||
 | 
						children: React.ReactNode;
 | 
				
			||||||
 | 
						color: string;
 | 
				
			||||||
 | 
						link: string;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const SocialCard = ({
 | 
				
			||||||
 | 
						children,
 | 
				
			||||||
 | 
						color,
 | 
				
			||||||
 | 
						link,
 | 
				
			||||||
 | 
					}: SocialCardProps): JSX.Element => {
 | 
				
			||||||
 | 
						return (
 | 
				
			||||||
 | 
							<div
 | 
				
			||||||
 | 
								className={`group relative flex h-24 w-36 min-w-max flex-shrink-0 rounded-xl shadow-xl ${color} m-2`}
 | 
				
			||||||
 | 
							>
 | 
				
			||||||
 | 
								{children}
 | 
				
			||||||
 | 
								<a
 | 
				
			||||||
 | 
									className="absolute top-0 left-0 right-0 bottom-0 hidden rounded-xl border border-accent bg-secondary bg-opacity-95 text-2xl shadow-xl group-hover:flex"
 | 
				
			||||||
 | 
									href={link}
 | 
				
			||||||
 | 
									rel="noreferrer"
 | 
				
			||||||
 | 
									target="_blank"
 | 
				
			||||||
 | 
								>
 | 
				
			||||||
 | 
									<FiExternalLink className="m-auto" />
 | 
				
			||||||
 | 
								</a>
 | 
				
			||||||
 | 
							</div>
 | 
				
			||||||
 | 
						);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
							
								
								
									
										345
									
								
								src/components/tools/FrequencyCalculator.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,345 @@
 | 
				
			|||||||
 | 
					import React, { useEffect } from "react";
 | 
				
			||||||
 | 
					import { Protobuf, Types } from "@meshtastic/meshtasticjs";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					interface Region {
 | 
				
			||||||
 | 
						freq_start: number;
 | 
				
			||||||
 | 
						freq_end: number;
 | 
				
			||||||
 | 
						duty_cycle: number;
 | 
				
			||||||
 | 
						spacing: number;
 | 
				
			||||||
 | 
						power_limit: number;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					interface Modem {
 | 
				
			||||||
 | 
						bw: number;
 | 
				
			||||||
 | 
						cr: number;
 | 
				
			||||||
 | 
						sf: number;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const RegionData = new Map<Protobuf.Config_LoRaConfig_RegionCode, Region>([
 | 
				
			||||||
 | 
						[
 | 
				
			||||||
 | 
							Protobuf.Config_LoRaConfig_RegionCode.US,
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								freq_start: 902.0,
 | 
				
			||||||
 | 
								freq_end: 928.0,
 | 
				
			||||||
 | 
								duty_cycle: 100,
 | 
				
			||||||
 | 
								spacing: 0,
 | 
				
			||||||
 | 
								power_limit: 30,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						],
 | 
				
			||||||
 | 
						[
 | 
				
			||||||
 | 
							Protobuf.Config_LoRaConfig_RegionCode.EU_433,
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								freq_start: 433.0,
 | 
				
			||||||
 | 
								freq_end: 434.0,
 | 
				
			||||||
 | 
								duty_cycle: 10,
 | 
				
			||||||
 | 
								spacing: 0,
 | 
				
			||||||
 | 
								power_limit: 12,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						],
 | 
				
			||||||
 | 
						[
 | 
				
			||||||
 | 
							Protobuf.Config_LoRaConfig_RegionCode.EU_868,
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								freq_start: 869.4,
 | 
				
			||||||
 | 
								freq_end: 869.65,
 | 
				
			||||||
 | 
								duty_cycle: 10,
 | 
				
			||||||
 | 
								spacing: 0,
 | 
				
			||||||
 | 
								power_limit: 27,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						],
 | 
				
			||||||
 | 
						[
 | 
				
			||||||
 | 
							Protobuf.Config_LoRaConfig_RegionCode.CN,
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								freq_start: 470.0,
 | 
				
			||||||
 | 
								freq_end: 510.0,
 | 
				
			||||||
 | 
								duty_cycle: 100,
 | 
				
			||||||
 | 
								spacing: 0,
 | 
				
			||||||
 | 
								power_limit: 19,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						],
 | 
				
			||||||
 | 
						[
 | 
				
			||||||
 | 
							Protobuf.Config_LoRaConfig_RegionCode.JP,
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								freq_start: 920.8,
 | 
				
			||||||
 | 
								freq_end: 927.8,
 | 
				
			||||||
 | 
								duty_cycle: 100,
 | 
				
			||||||
 | 
								spacing: 0,
 | 
				
			||||||
 | 
								power_limit: 16,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						],
 | 
				
			||||||
 | 
						[
 | 
				
			||||||
 | 
							Protobuf.Config_LoRaConfig_RegionCode.ANZ,
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								freq_start: 915.0,
 | 
				
			||||||
 | 
								freq_end: 928.0,
 | 
				
			||||||
 | 
								duty_cycle: 100,
 | 
				
			||||||
 | 
								spacing: 0,
 | 
				
			||||||
 | 
								power_limit: 30,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						],
 | 
				
			||||||
 | 
						[
 | 
				
			||||||
 | 
							Protobuf.Config_LoRaConfig_RegionCode.RU,
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								freq_start: 868.7,
 | 
				
			||||||
 | 
								freq_end: 869.2,
 | 
				
			||||||
 | 
								duty_cycle: 100,
 | 
				
			||||||
 | 
								spacing: 0,
 | 
				
			||||||
 | 
								power_limit: 20,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						],
 | 
				
			||||||
 | 
						[
 | 
				
			||||||
 | 
							Protobuf.Config_LoRaConfig_RegionCode.KR,
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								freq_start: 920.0,
 | 
				
			||||||
 | 
								freq_end: 923.0,
 | 
				
			||||||
 | 
								duty_cycle: 100,
 | 
				
			||||||
 | 
								spacing: 0,
 | 
				
			||||||
 | 
								power_limit: 0,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						],
 | 
				
			||||||
 | 
						[
 | 
				
			||||||
 | 
							Protobuf.Config_LoRaConfig_RegionCode.TW,
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								freq_start: 920.0,
 | 
				
			||||||
 | 
								freq_end: 925.0,
 | 
				
			||||||
 | 
								duty_cycle: 100,
 | 
				
			||||||
 | 
								spacing: 0,
 | 
				
			||||||
 | 
								power_limit: 0,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						],
 | 
				
			||||||
 | 
						[
 | 
				
			||||||
 | 
							Protobuf.Config_LoRaConfig_RegionCode.IN,
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								freq_start: 865.0,
 | 
				
			||||||
 | 
								freq_end: 867.0,
 | 
				
			||||||
 | 
								duty_cycle: 100,
 | 
				
			||||||
 | 
								spacing: 0,
 | 
				
			||||||
 | 
								power_limit: 30,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						],
 | 
				
			||||||
 | 
						[
 | 
				
			||||||
 | 
							Protobuf.Config_LoRaConfig_RegionCode.NZ_865,
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								freq_start: 864.0,
 | 
				
			||||||
 | 
								freq_end: 868.0,
 | 
				
			||||||
 | 
								duty_cycle: 100,
 | 
				
			||||||
 | 
								spacing: 0,
 | 
				
			||||||
 | 
								power_limit: 36,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						],
 | 
				
			||||||
 | 
						[
 | 
				
			||||||
 | 
							Protobuf.Config_LoRaConfig_RegionCode.TH,
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								freq_start: 920.0,
 | 
				
			||||||
 | 
								freq_end: 925.0,
 | 
				
			||||||
 | 
								duty_cycle: 100,
 | 
				
			||||||
 | 
								spacing: 0,
 | 
				
			||||||
 | 
								power_limit: 16,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						],
 | 
				
			||||||
 | 
						[
 | 
				
			||||||
 | 
							Protobuf.Config_LoRaConfig_RegionCode.UA_433,
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								freq_start: 433.0,
 | 
				
			||||||
 | 
								freq_end: 434.7,
 | 
				
			||||||
 | 
								duty_cycle: 10,
 | 
				
			||||||
 | 
								spacing: 0,
 | 
				
			||||||
 | 
								power_limit: 10,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						],
 | 
				
			||||||
 | 
						[
 | 
				
			||||||
 | 
							Protobuf.Config_LoRaConfig_RegionCode.UA_868,
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								freq_start: 868.0,
 | 
				
			||||||
 | 
								freq_end: 868.6,
 | 
				
			||||||
 | 
								duty_cycle: 1,
 | 
				
			||||||
 | 
								spacing: 0,
 | 
				
			||||||
 | 
								power_limit: 14,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						],
 | 
				
			||||||
 | 
						[
 | 
				
			||||||
 | 
							Protobuf.Config_LoRaConfig_RegionCode.LORA_24,
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								freq_start: 2400.0,
 | 
				
			||||||
 | 
								freq_end: 2483.5,
 | 
				
			||||||
 | 
								duty_cycle: 100,
 | 
				
			||||||
 | 
								spacing: 0,
 | 
				
			||||||
 | 
								power_limit: 10,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						],
 | 
				
			||||||
 | 
						[
 | 
				
			||||||
 | 
							Protobuf.Config_LoRaConfig_RegionCode.UNSET,
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								freq_start: 902.0,
 | 
				
			||||||
 | 
								freq_end: 928.0,
 | 
				
			||||||
 | 
								duty_cycle: 100,
 | 
				
			||||||
 | 
								spacing: 0,
 | 
				
			||||||
 | 
								power_limit: 30,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						],
 | 
				
			||||||
 | 
					]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const modemPresets = new Map<Protobuf.Config_LoRaConfig_ModemPreset, Modem>([
 | 
				
			||||||
 | 
						[
 | 
				
			||||||
 | 
							Protobuf.Config_LoRaConfig_ModemPreset.SHORT_FAST,
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								bw: 250,
 | 
				
			||||||
 | 
								cr: 8,
 | 
				
			||||||
 | 
								sf: 7,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						],
 | 
				
			||||||
 | 
						[
 | 
				
			||||||
 | 
							Protobuf.Config_LoRaConfig_ModemPreset.SHORT_SLOW,
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								bw: 250,
 | 
				
			||||||
 | 
								cr: 8,
 | 
				
			||||||
 | 
								sf: 8,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						],
 | 
				
			||||||
 | 
						[
 | 
				
			||||||
 | 
							Protobuf.Config_LoRaConfig_ModemPreset.MEDIUM_FAST,
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								bw: 250,
 | 
				
			||||||
 | 
								cr: 8,
 | 
				
			||||||
 | 
								sf: 9,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						],
 | 
				
			||||||
 | 
						[
 | 
				
			||||||
 | 
							Protobuf.Config_LoRaConfig_ModemPreset.MEDIUM_SLOW,
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								bw: 250,
 | 
				
			||||||
 | 
								cr: 8,
 | 
				
			||||||
 | 
								sf: 10,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						],
 | 
				
			||||||
 | 
						[
 | 
				
			||||||
 | 
							Protobuf.Config_LoRaConfig_ModemPreset.LONG_FAST,
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								bw: 250,
 | 
				
			||||||
 | 
								cr: 8,
 | 
				
			||||||
 | 
								sf: 11,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						],
 | 
				
			||||||
 | 
						[
 | 
				
			||||||
 | 
							Protobuf.Config_LoRaConfig_ModemPreset.LONG_MODERATE,
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								bw: 125,
 | 
				
			||||||
 | 
								cr: 8,
 | 
				
			||||||
 | 
								sf: 11,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						],
 | 
				
			||||||
 | 
						[
 | 
				
			||||||
 | 
							Protobuf.Config_LoRaConfig_ModemPreset.LONG_SLOW,
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								bw: 125,
 | 
				
			||||||
 | 
								cr: 8,
 | 
				
			||||||
 | 
								sf: 12,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						],
 | 
				
			||||||
 | 
						[
 | 
				
			||||||
 | 
							Protobuf.Config_LoRaConfig_ModemPreset.VERY_LONG_SLOW,
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								bw: 62.5,
 | 
				
			||||||
 | 
								cr: 8,
 | 
				
			||||||
 | 
								sf: 12,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						],
 | 
				
			||||||
 | 
					]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const FrequencyCalculator = (): JSX.Element => {
 | 
				
			||||||
 | 
						const [modemPreset, setModemPreset] =
 | 
				
			||||||
 | 
							React.useState<Protobuf.Config_LoRaConfig_ModemPreset>(
 | 
				
			||||||
 | 
								Protobuf.Config_LoRaConfig_ModemPreset.LONG_FAST,
 | 
				
			||||||
 | 
							);
 | 
				
			||||||
 | 
						const [region, setRegion] =
 | 
				
			||||||
 | 
							React.useState<Protobuf.Config_LoRaConfig_RegionCode>(
 | 
				
			||||||
 | 
								Protobuf.Config_LoRaConfig_RegionCode.US,
 | 
				
			||||||
 | 
							);
 | 
				
			||||||
 | 
						const [channel, setChannel] = React.useState<Types.ChannelNumber>(
 | 
				
			||||||
 | 
							Types.ChannelNumber.PRIMARY,
 | 
				
			||||||
 | 
						);
 | 
				
			||||||
 | 
						const [numChannels, setNumChannels] = React.useState<number>(0);
 | 
				
			||||||
 | 
						const [channelFrequency, setChannelFrequency] = React.useState<number>(0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						useEffect(() => {
 | 
				
			||||||
 | 
							const selectedRegion = RegionData.get(region);
 | 
				
			||||||
 | 
							const selectedModemPreset = modemPresets.get(modemPreset);
 | 
				
			||||||
 | 
							const calculatedNumChannels = Math.floor(
 | 
				
			||||||
 | 
								(selectedRegion.freq_end - selectedRegion.freq_start) /
 | 
				
			||||||
 | 
									(selectedRegion.spacing + selectedModemPreset.bw / 1000),
 | 
				
			||||||
 | 
							);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							setNumChannels(calculatedNumChannels);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							let updatedChannel = channel;
 | 
				
			||||||
 | 
							if (updatedChannel >= calculatedNumChannels) {
 | 
				
			||||||
 | 
								updatedChannel = 0;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							setChannel(updatedChannel);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							setChannelFrequency(
 | 
				
			||||||
 | 
								selectedRegion.freq_start +
 | 
				
			||||||
 | 
									selectedModemPreset.bw / 2000 +
 | 
				
			||||||
 | 
									updatedChannel * (selectedModemPreset.bw / 1000),
 | 
				
			||||||
 | 
							);
 | 
				
			||||||
 | 
						}, [modemPreset, region, channel]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return (
 | 
				
			||||||
 | 
							<div className="flex flex-col border-l-[5px] shadow-md my-4 border-accent rounded-lg p-4 bg-secondary gap-2">
 | 
				
			||||||
 | 
								<div className="flex gap-2">
 | 
				
			||||||
 | 
									<label>Modem Preset:</label>
 | 
				
			||||||
 | 
									<select
 | 
				
			||||||
 | 
										value={modemPreset}
 | 
				
			||||||
 | 
										onChange={(e) =>
 | 
				
			||||||
 | 
											setModemPreset(
 | 
				
			||||||
 | 
												parseInt(
 | 
				
			||||||
 | 
													e.target.value,
 | 
				
			||||||
 | 
												) as Protobuf.Config_LoRaConfig_ModemPreset,
 | 
				
			||||||
 | 
											)
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									>
 | 
				
			||||||
 | 
										{Array.from(modemPresets.keys()).map((key) => (
 | 
				
			||||||
 | 
											<option key={key} value={key}>
 | 
				
			||||||
 | 
												{Protobuf.Config_LoRaConfig_ModemPreset[key]}
 | 
				
			||||||
 | 
											</option>
 | 
				
			||||||
 | 
										))}
 | 
				
			||||||
 | 
									</select>
 | 
				
			||||||
 | 
								</div>
 | 
				
			||||||
 | 
								<div className="flex gap-2">
 | 
				
			||||||
 | 
									<label>Region:</label>
 | 
				
			||||||
 | 
									<select
 | 
				
			||||||
 | 
										value={region}
 | 
				
			||||||
 | 
										onChange={(e) => setRegion(parseInt(e.target.value))}
 | 
				
			||||||
 | 
									>
 | 
				
			||||||
 | 
										{Array.from(RegionData.keys()).map((key) => (
 | 
				
			||||||
 | 
											<option key={key} value={key}>
 | 
				
			||||||
 | 
												{Protobuf.Config_LoRaConfig_RegionCode[key]}
 | 
				
			||||||
 | 
											</option>
 | 
				
			||||||
 | 
										))}
 | 
				
			||||||
 | 
									</select>
 | 
				
			||||||
 | 
								</div>
 | 
				
			||||||
 | 
								<div className="flex gap-2">
 | 
				
			||||||
 | 
									<label>Channel:</label>
 | 
				
			||||||
 | 
									<select
 | 
				
			||||||
 | 
										value={channel}
 | 
				
			||||||
 | 
										onChange={(e) => setChannel(parseInt(e.target.value))}
 | 
				
			||||||
 | 
									>
 | 
				
			||||||
 | 
										{Array.from(Array(numChannels).keys()).map((key) => (
 | 
				
			||||||
 | 
											<option key={key} value={key}>
 | 
				
			||||||
 | 
												{key + 1}
 | 
				
			||||||
 | 
											</option>
 | 
				
			||||||
 | 
										))}
 | 
				
			||||||
 | 
									</select>
 | 
				
			||||||
 | 
								</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								<div className="flex gap-2">
 | 
				
			||||||
 | 
									<label className="font-semibold">Number of channels:</label>
 | 
				
			||||||
 | 
									<input type="number" disabled value={numChannels} />
 | 
				
			||||||
 | 
								</div>
 | 
				
			||||||
 | 
								<div className="flex gap-2">
 | 
				
			||||||
 | 
									<label className="font-semibold">Channel Frequency:</label>
 | 
				
			||||||
 | 
									<input type="number" disabled value={channelFrequency} />
 | 
				
			||||||
 | 
								</div>
 | 
				
			||||||
 | 
							</div>
 | 
				
			||||||
 | 
						);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
							
								
								
									
										208
									
								
								src/css/custom.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,208 @@
 | 
				
			|||||||
 | 
					@tailwind base;
 | 
				
			||||||
 | 
					@tailwind components;
 | 
				
			||||||
 | 
					@tailwind utilities;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* You can override the default Infima variables here. */
 | 
				
			||||||
 | 
					:root {
 | 
				
			||||||
 | 
					  --ifm-color-primary: #eab167;
 | 
				
			||||||
 | 
					  --ifm-color-primary-dark: rgb(175, 102, 33);
 | 
				
			||||||
 | 
					  --ifm-color-primary-darker: rgb(165, 85, 31);
 | 
				
			||||||
 | 
					  --ifm-color-primary-darkest: rgb(136, 75, 26);
 | 
				
			||||||
 | 
					  --ifm-color-primary-light: rgb(203, 130, 70);
 | 
				
			||||||
 | 
					  --ifm-color-primary-lighter: rgb(212, 164, 102);
 | 
				
			||||||
 | 
					  --ifm-color-primary-lightest: rgb(224, 199, 146);
 | 
				
			||||||
 | 
					  --ifm-list-item-margin: 0;
 | 
				
			||||||
 | 
					  --ifm-code-font-size: 95%;
 | 
				
			||||||
 | 
					  --ifm-z-index-fixed: 1;
 | 
				
			||||||
 | 
					  --accent: #eab167;
 | 
				
			||||||
 | 
					  --base: #f3f4f6;
 | 
				
			||||||
 | 
					  --primary: #ffffff;
 | 
				
			||||||
 | 
					  --secondary: #e5e7eb;
 | 
				
			||||||
 | 
					  --tertiary: #d1d5db;
 | 
				
			||||||
 | 
					  --mute: #6b7280;
 | 
				
			||||||
 | 
					  --primaryInv: #242526;
 | 
				
			||||||
 | 
					  --secondaryInv: #18191a;
 | 
				
			||||||
 | 
					  --tertiaryInv: #4c4e50;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[data-theme="dark"] {
 | 
				
			||||||
 | 
					  --base: #38393b;
 | 
				
			||||||
 | 
					  --primary: #242526;
 | 
				
			||||||
 | 
					  --secondary: #18191a;
 | 
				
			||||||
 | 
					  --tertiary: #4c4e50;
 | 
				
			||||||
 | 
					  --mute: #9ca3af;
 | 
				
			||||||
 | 
					  --primaryInv: #ffffff;
 | 
				
			||||||
 | 
					  --secondaryInv: #e5e7eb;
 | 
				
			||||||
 | 
					  --tertiaryInv: #d1d5db;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.docusaurus-highlight-code-line {
 | 
				
			||||||
 | 
					  background-color: rgb(72, 77, 91);
 | 
				
			||||||
 | 
					  display: block;
 | 
				
			||||||
 | 
					  margin: 0 calc(-1 * var(--ifm-pre-padding));
 | 
				
			||||||
 | 
					  padding: 0 var(--ifm-pre-padding);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.header-github-link:hover {
 | 
				
			||||||
 | 
					  opacity: 0.6;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.header-github-link:before {
 | 
				
			||||||
 | 
					  content: "";
 | 
				
			||||||
 | 
					  width: 24px;
 | 
				
			||||||
 | 
					  height: 24px;
 | 
				
			||||||
 | 
					  display: flex;
 | 
				
			||||||
 | 
					  background: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12'/%3E%3C/svg%3E")
 | 
				
			||||||
 | 
					    no-repeat;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					html[data-theme="dark"] .header-github-link:before {
 | 
				
			||||||
 | 
					  background: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill='white' d='M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12'/%3E%3C/svg%3E")
 | 
				
			||||||
 | 
					    no-repeat;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					@keyframes pulse {
 | 
				
			||||||
 | 
					  0% {
 | 
				
			||||||
 | 
					    transform: scale(0.98);
 | 
				
			||||||
 | 
					    box-shadow: 0 0 0 0 rgba(0, 0, 0, 0.7);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  70% {
 | 
				
			||||||
 | 
					    transform: scale(1);
 | 
				
			||||||
 | 
					    box-shadow: 0 0 0 10px rgba(0, 0, 0, 0);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  100% {
 | 
				
			||||||
 | 
					    transform: scale(0.98);
 | 
				
			||||||
 | 
					    box-shadow: 0 0 0 0 rgba(0, 0, 0, 0);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.cta--button {
 | 
				
			||||||
 | 
					  --ifm-button-border-color: var(--ifm-link-color);
 | 
				
			||||||
 | 
					  color: var(--ifm-link-color);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.split-container {
 | 
				
			||||||
 | 
					  display: flex;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.split-item {
 | 
				
			||||||
 | 
					  flex: 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.indexCtasBody {
 | 
				
			||||||
 | 
					  --ifm-button-size-multiplier: 1.6;
 | 
				
			||||||
 | 
					  display: flex;
 | 
				
			||||||
 | 
					  flex-wrap: wrap;
 | 
				
			||||||
 | 
					  align-items: center;
 | 
				
			||||||
 | 
					  justify-content: center;
 | 
				
			||||||
 | 
					  margin-top: 24px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.indexCtasBody a:last-of-type {
 | 
				
			||||||
 | 
					  margin: 20px 36px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.indexCtas {
 | 
				
			||||||
 | 
					  --ifm-button-size-multiplier: 1.6;
 | 
				
			||||||
 | 
					  display: flex;
 | 
				
			||||||
 | 
					  flex-wrap: wrap;
 | 
				
			||||||
 | 
					  align-items: center;
 | 
				
			||||||
 | 
					  justify-content: center;
 | 
				
			||||||
 | 
					  margin-top: 24px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.indexCtas a {
 | 
				
			||||||
 | 
					  color: var(--ifm-font-color-base-inverse);
 | 
				
			||||||
 | 
					  --ifm-button-border-color: var(--ifm-font-color-base-inverse);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.indexCtas a:hover {
 | 
				
			||||||
 | 
					  color: rgb(77, 77, 77);
 | 
				
			||||||
 | 
					  --ifm-button-border-color: rgb(77, 77, 77);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.indexCtas a:last-of-type {
 | 
				
			||||||
 | 
					  margin: 20px 36px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.theme-doc-markdown {
 | 
				
			||||||
 | 
					  max-width: none;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					a + .navbar__link {
 | 
				
			||||||
 | 
					  display: flex;
 | 
				
			||||||
 | 
					  gap: 2px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					a + .navbar__link > svg {
 | 
				
			||||||
 | 
					  margin-top: auto;
 | 
				
			||||||
 | 
					  margin-bottom: auto;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@layer base {
 | 
				
			||||||
 | 
					  .markdown {
 | 
				
			||||||
 | 
					    @apply prose prose-lg;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  .markdown img {
 | 
				
			||||||
 | 
					    @apply rounded-lg mx-auto;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  [data-theme="dark"] .markdown {
 | 
				
			||||||
 | 
					    @apply prose-invert;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  [data-theme="dark"] .hideDark {
 | 
				
			||||||
 | 
					    @apply hidden;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  [data-theme="dark"] .hideLight {
 | 
				
			||||||
 | 
					    @apply block;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  .hideLight {
 | 
				
			||||||
 | 
					    @apply hidden;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  .hideDark {
 | 
				
			||||||
 | 
					    @apply block;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.markdown :where(li):not(:where([class~="not-prose"] *)) {
 | 
				
			||||||
 | 
					  margin-bottom: 0;
 | 
				
			||||||
 | 
					  margin-top: 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.markdown
 | 
				
			||||||
 | 
					  :where(ul ul, ul ol, ol ul, ol ol):not(:where([class~="not-prose"] *)) {
 | 
				
			||||||
 | 
					  margin-bottom: 0;
 | 
				
			||||||
 | 
					  margin-top: 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					h1,
 | 
				
			||||||
 | 
					h2,
 | 
				
			||||||
 | 
					h3,
 | 
				
			||||||
 | 
					h4,
 | 
				
			||||||
 | 
					h5,
 | 
				
			||||||
 | 
					h6 {
 | 
				
			||||||
 | 
					  font-weight: var(--ifm-heading-font-weight);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					h1 {
 | 
				
			||||||
 | 
					  font-size: var(--ifm-h1-font-size);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					h2 {
 | 
				
			||||||
 | 
					  font-size: var(--ifm-h2-font-size);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					h3 {
 | 
				
			||||||
 | 
					  font-size: var(--ifm-h3-font-size);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					h4 {
 | 
				
			||||||
 | 
					  font-size: var(--ifm-h4-font-size);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					h5 {
 | 
				
			||||||
 | 
					  font-size: var(--ifm-h5-font-size);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					h6 {
 | 
				
			||||||
 | 
					  font-size: var(--ifm-h6-font-size);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										29
									
								
								src/hooks/useFilteredNetworks.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,29 @@
 | 
				
			|||||||
 | 
					import React from "react";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { Showcase } from "../utils/apiTypes";
 | 
				
			||||||
 | 
					import { useSelectedTags } from "./useSelectedTags";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const filterNetworks = (
 | 
				
			||||||
 | 
						showcaseNetworks: Showcase[],
 | 
				
			||||||
 | 
						selectedTags: string[],
 | 
				
			||||||
 | 
					) => {
 | 
				
			||||||
 | 
						if (selectedTags.length === 0) {
 | 
				
			||||||
 | 
							return showcaseNetworks;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return showcaseNetworks.filter((showcaseNetwork) => {
 | 
				
			||||||
 | 
							if (showcaseNetwork.tags.length === 0) {
 | 
				
			||||||
 | 
								return false;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return selectedTags.every((queryTag) =>
 | 
				
			||||||
 | 
								showcaseNetwork.tags.find((searchTag) => searchTag.label === queryTag),
 | 
				
			||||||
 | 
							);
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const useFilteredNetworks = (networks: Showcase[]) => {
 | 
				
			||||||
 | 
						const selectedTags = useSelectedTags();
 | 
				
			||||||
 | 
						return React.useMemo(
 | 
				
			||||||
 | 
							() => filterNetworks(networks, selectedTags),
 | 
				
			||||||
 | 
							[selectedTags],
 | 
				
			||||||
 | 
						);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
							
								
								
									
										16
									
								
								src/hooks/useSelectedTags.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,16 @@
 | 
				
			|||||||
 | 
					import React from "react";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { useLocation } from "@docusaurus/router";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { readSearchTags } from "../pages/showcase/_components/TagSelect";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const useSelectedTags = () => {
 | 
				
			||||||
 | 
						const location = useLocation();
 | 
				
			||||||
 | 
						const [selectedTags, setSelectedTags] = React.useState<string[]>([]);
 | 
				
			||||||
 | 
						React.useEffect(() => {
 | 
				
			||||||
 | 
							const tags = readSearchTags(location.search);
 | 
				
			||||||
 | 
							setSelectedTags(tags);
 | 
				
			||||||
 | 
						}, [location]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return selectedTags;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
							
								
								
									
										44
									
								
								src/pages/credits/_components/Avatar.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,44 @@
 | 
				
			|||||||
 | 
					import React from "react";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export interface avatarProps {
 | 
				
			||||||
 | 
						imgUrl: string;
 | 
				
			||||||
 | 
						name?: string;
 | 
				
			||||||
 | 
						userName?: string;
 | 
				
			||||||
 | 
						description?: string;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export interface avatarLayoutProps {
 | 
				
			||||||
 | 
						list: list[];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const Avatar = ({
 | 
				
			||||||
 | 
						imgUrl,
 | 
				
			||||||
 | 
						name,
 | 
				
			||||||
 | 
						description,
 | 
				
			||||||
 | 
					}: avatarProps): JSX.Element => {
 | 
				
			||||||
 | 
						return (
 | 
				
			||||||
 | 
							<div className="card m-4 border-2 border-secondary">
 | 
				
			||||||
 | 
								<div className="card__body">
 | 
				
			||||||
 | 
									<div className="avatar">
 | 
				
			||||||
 | 
										<img className="avatar__photo avatar__photo--sm" src={imgUrl} />
 | 
				
			||||||
 | 
										<div className="avatar__intro">
 | 
				
			||||||
 | 
											<div className="avatar__name">{name}</div>
 | 
				
			||||||
 | 
											<small className="avatar__subtitle">{description}</small>
 | 
				
			||||||
 | 
										</div>
 | 
				
			||||||
 | 
									</div>
 | 
				
			||||||
 | 
								</div>
 | 
				
			||||||
 | 
							</div>
 | 
				
			||||||
 | 
						);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const AvatarLayout = ({ list }: avatarLayoutProps): JSX.Element => {
 | 
				
			||||||
 | 
						return (
 | 
				
			||||||
 | 
							<div className="container">
 | 
				
			||||||
 | 
								<div className="flex flex-wrap justify-center bg-primary">
 | 
				
			||||||
 | 
									{list.map(() => {
 | 
				
			||||||
 | 
										return <Avatar />;
 | 
				
			||||||
 | 
									})}
 | 
				
			||||||
 | 
								</div>
 | 
				
			||||||
 | 
							</div>
 | 
				
			||||||
 | 
						);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
							
								
								
									
										165
									
								
								src/pages/credits/index.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,165 @@
 | 
				
			|||||||
 | 
					import React from "react";
 | 
				
			||||||
 | 
					import Layout from "@theme/Layout";
 | 
				
			||||||
 | 
					import Link from "@docusaurus/Link";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { AvatarLayout } from "./_components/Avatar";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const Credits = (): JSX.Element => {
 | 
				
			||||||
 | 
						const partnerLogos = [
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name: "Vercel",
 | 
				
			||||||
 | 
								url: "/2.0/vercel-logotype-dark.svg",
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name: "Cloudflare",
 | 
				
			||||||
 | 
								url: "/2.0/CF_logo_horizontal_blktype.svg",
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name: "RAK Wireless",
 | 
				
			||||||
 | 
								url: "/2.0/RAK-blue-main.svg",
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name: "Open Collective",
 | 
				
			||||||
 | 
								url: "/2.0/opencollectivelogo.svg",
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name: "LILYGO",
 | 
				
			||||||
 | 
								url: "/2.0/LILYGO.png",
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name: "Discord",
 | 
				
			||||||
 | 
								url: "/2.0/discord.svg",
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						];
 | 
				
			||||||
 | 
						return (
 | 
				
			||||||
 | 
							<Layout
 | 
				
			||||||
 | 
								title="Credits"
 | 
				
			||||||
 | 
								description="Meshtastic is made possible by the following people & organizations."
 | 
				
			||||||
 | 
							>
 | 
				
			||||||
 | 
								<main className="relative mt-20">
 | 
				
			||||||
 | 
									<div className="container mx-auto p-6 leading-normal space-y-4">
 | 
				
			||||||
 | 
										<h1>Credits</h1>
 | 
				
			||||||
 | 
										<p>
 | 
				
			||||||
 | 
											Meshtastic is community driven. Thousands of hours have been donated
 | 
				
			||||||
 | 
											by volunteers who want to develop this amazing project. Whether
 | 
				
			||||||
 | 
											you've submitted a pull request or triaged a bug in our
 | 
				
			||||||
 | 
											Discord/Forum. You've made Meshtastic possible. Thank you for your
 | 
				
			||||||
 | 
											contributions.
 | 
				
			||||||
 | 
										</p>
 | 
				
			||||||
 | 
										<p>
 | 
				
			||||||
 | 
											We would also like to recognize those who have donated financially
 | 
				
			||||||
 | 
											to the project. As Meshtastic has grown, we've aquired some ongoing
 | 
				
			||||||
 | 
											costs to keep the project running. Thank you for your generous
 | 
				
			||||||
 | 
											donations.
 | 
				
			||||||
 | 
										</p>
 | 
				
			||||||
 | 
									</div>
 | 
				
			||||||
 | 
									<div className="container mx-auto p-6 leading-normal space-y-4">
 | 
				
			||||||
 | 
										<h2>Fiscal Sponsors</h2>
 | 
				
			||||||
 | 
										<p>
 | 
				
			||||||
 | 
											We have partnered with both the{" "}
 | 
				
			||||||
 | 
											<a
 | 
				
			||||||
 | 
												className="underline"
 | 
				
			||||||
 | 
												href="https://opencollective.com"
 | 
				
			||||||
 | 
												target="_blank"
 | 
				
			||||||
 | 
											>
 | 
				
			||||||
 | 
												Open Collective
 | 
				
			||||||
 | 
											</a>{" "}
 | 
				
			||||||
 | 
											and the{" "}
 | 
				
			||||||
 | 
											<a
 | 
				
			||||||
 | 
												className="underline"
 | 
				
			||||||
 | 
												href="https://www.oscollective.org"
 | 
				
			||||||
 | 
												target="_blank"
 | 
				
			||||||
 | 
											>
 | 
				
			||||||
 | 
												Open Source Collective
 | 
				
			||||||
 | 
											</a>{" "}
 | 
				
			||||||
 | 
											to help us with a fiscal management framework and banking needs.
 | 
				
			||||||
 | 
											They help support over three thousand open source projects including
 | 
				
			||||||
 | 
											the PHP Foundation, F-Droid, Sonarr, LinuxServer and DarkReader. We
 | 
				
			||||||
 | 
											are in good hands and good company.
 | 
				
			||||||
 | 
										</p>
 | 
				
			||||||
 | 
										<p>
 | 
				
			||||||
 | 
											As with everything we do here, Open Collective provides a fully
 | 
				
			||||||
 | 
											transparent framework for our budget and expenses. You can see what
 | 
				
			||||||
 | 
											we’re bringing in, who is spending money and where that money is
 | 
				
			||||||
 | 
											going{" "}
 | 
				
			||||||
 | 
											<a
 | 
				
			||||||
 | 
												className="underline"
 | 
				
			||||||
 | 
												href="https://opencollective.com/meshtastic"
 | 
				
			||||||
 | 
												target="_blank"
 | 
				
			||||||
 | 
											>
 | 
				
			||||||
 | 
												here
 | 
				
			||||||
 | 
											</a>
 | 
				
			||||||
 | 
											.
 | 
				
			||||||
 | 
										</p>
 | 
				
			||||||
 | 
										<p>
 | 
				
			||||||
 | 
											In addition to our partnership with Open Collective and Open Source
 | 
				
			||||||
 | 
											Collective, we have also been approved into the{" "}
 | 
				
			||||||
 | 
											<a
 | 
				
			||||||
 | 
												className="underline"
 | 
				
			||||||
 | 
												href="https://github.com/sponsors"
 | 
				
			||||||
 | 
												target="_blank"
 | 
				
			||||||
 | 
											>
 | 
				
			||||||
 | 
												GitHub Sponsors
 | 
				
			||||||
 | 
											</a>{" "}
 | 
				
			||||||
 | 
											program where we can set fundraising goals with GitHub.
 | 
				
			||||||
 | 
										</p>
 | 
				
			||||||
 | 
										<p>
 | 
				
			||||||
 | 
											All donations made through GitHub will be deposited to our account
 | 
				
			||||||
 | 
											with the Open Source Collective and managed by the Open Collective.
 | 
				
			||||||
 | 
											This means we have a single place to monitor and maintain
 | 
				
			||||||
 | 
											transparency of our finances.
 | 
				
			||||||
 | 
										</p>
 | 
				
			||||||
 | 
										<p>If you are able, please contribute to this amazing project.</p>
 | 
				
			||||||
 | 
										<div className="indexCtasBody">
 | 
				
			||||||
 | 
											<Link
 | 
				
			||||||
 | 
												className={"button button--outline  button--lg cta--button"}
 | 
				
			||||||
 | 
												to={"https://opencollective.com/meshtastic/donate"}
 | 
				
			||||||
 | 
											>
 | 
				
			||||||
 | 
												Sponsor Meshtastic
 | 
				
			||||||
 | 
											</Link>
 | 
				
			||||||
 | 
										</div>
 | 
				
			||||||
 | 
										<h3>
 | 
				
			||||||
 | 
											Open Collective Donations
 | 
				
			||||||
 | 
											{/*Open Collective Donations*/}
 | 
				
			||||||
 | 
											<AvatarLayout list={[]} />
 | 
				
			||||||
 | 
										</h3>
 | 
				
			||||||
 | 
										<h3>
 | 
				
			||||||
 | 
											GitHub Sponsor Donations
 | 
				
			||||||
 | 
											{/*GitHub Sponsor Donations*/}
 | 
				
			||||||
 | 
											<AvatarLayout list={[]} />
 | 
				
			||||||
 | 
										</h3>
 | 
				
			||||||
 | 
									</div>
 | 
				
			||||||
 | 
									<div className="container mx-auto p-6 leading-normal space-y-4">
 | 
				
			||||||
 | 
										<h2>Partnerships</h2>
 | 
				
			||||||
 | 
										<div className="mt-12 grid grid-cols-2 gap-0.5 md:grid-cols-3 lg:mt-0 lg:grid-cols-2">
 | 
				
			||||||
 | 
											{partnerLogos.map((logo) => (
 | 
				
			||||||
 | 
												<div
 | 
				
			||||||
 | 
													key={logo.name}
 | 
				
			||||||
 | 
													className="col-span-1 flex justify-center bg-gray-50 py-8 px-8"
 | 
				
			||||||
 | 
												>
 | 
				
			||||||
 | 
													<img className="max-h-12" src={logo.url} alt={logo.name} />
 | 
				
			||||||
 | 
												</div>
 | 
				
			||||||
 | 
											))}
 | 
				
			||||||
 | 
										</div>
 | 
				
			||||||
 | 
									</div>
 | 
				
			||||||
 | 
									<div className="container mx-auto p-6 leading-normal space-y-4">
 | 
				
			||||||
 | 
										<h2>Contributors</h2>
 | 
				
			||||||
 | 
										<p>
 | 
				
			||||||
 | 
											Literally thousands of hours have gone into creating, maintaining,
 | 
				
			||||||
 | 
											and improving Meshtastic. Without our contributors none of this
 | 
				
			||||||
 | 
											would be possible. Thank you for donating the time for each and
 | 
				
			||||||
 | 
											every commit, issue, and pull request.
 | 
				
			||||||
 | 
										</p>
 | 
				
			||||||
 | 
										{/*GitHub Organization Contributors*/}
 | 
				
			||||||
 | 
										<AvatarLayout list={[]} />
 | 
				
			||||||
 | 
									</div>
 | 
				
			||||||
 | 
									{/*Admin Bios*/}
 | 
				
			||||||
 | 
									<div className="container mx-auto p-6 leading-normal space-y-4">
 | 
				
			||||||
 | 
										<AvatarLayout list={[]} />
 | 
				
			||||||
 | 
									</div>
 | 
				
			||||||
 | 
								</main>
 | 
				
			||||||
 | 
							</Layout>
 | 
				
			||||||
 | 
						);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default Credits;
 | 
				
			||||||
							
								
								
									
										146
									
								
								src/pages/downloads/_components/DownloadCard.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,146 @@
 | 
				
			|||||||
 | 
					import React from "react";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export interface downloadCardProps {
 | 
				
			||||||
 | 
						client: string;
 | 
				
			||||||
 | 
						imgUrl: string;
 | 
				
			||||||
 | 
						url: string;
 | 
				
			||||||
 | 
						imgUrl2: string;
 | 
				
			||||||
 | 
						url2: string;
 | 
				
			||||||
 | 
						notes: string;
 | 
				
			||||||
 | 
						buttonText: string;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const DownloadCard = ({
 | 
				
			||||||
 | 
						client,
 | 
				
			||||||
 | 
						imgUrl,
 | 
				
			||||||
 | 
						url,
 | 
				
			||||||
 | 
						imgUrl2,
 | 
				
			||||||
 | 
						url2,
 | 
				
			||||||
 | 
						notes,
 | 
				
			||||||
 | 
						buttonText,
 | 
				
			||||||
 | 
					}: downloadCardProps): JSX.Element => {
 | 
				
			||||||
 | 
						return (
 | 
				
			||||||
 | 
							<div className="card">
 | 
				
			||||||
 | 
								<div
 | 
				
			||||||
 | 
									className="card__header"
 | 
				
			||||||
 | 
									style={{ display: "flex", justifyContent: "space-between" }}
 | 
				
			||||||
 | 
								>
 | 
				
			||||||
 | 
									<h3>{client}</h3>
 | 
				
			||||||
 | 
								</div>
 | 
				
			||||||
 | 
								<div
 | 
				
			||||||
 | 
									className="card__body"
 | 
				
			||||||
 | 
									style={{ display: "flex", justifyContent: "center" }}
 | 
				
			||||||
 | 
								>
 | 
				
			||||||
 | 
									{buttonText ? (
 | 
				
			||||||
 | 
										<a href={url} className="button button--secondary button--block">
 | 
				
			||||||
 | 
											{buttonText}
 | 
				
			||||||
 | 
										</a>
 | 
				
			||||||
 | 
									) : (
 | 
				
			||||||
 | 
										<div>
 | 
				
			||||||
 | 
											<a href={url}>
 | 
				
			||||||
 | 
												<img alt="img1" style={{ height: "4rem" }} src={imgUrl} />
 | 
				
			||||||
 | 
											</a>
 | 
				
			||||||
 | 
											<a href={url2}>
 | 
				
			||||||
 | 
												<img alt="img2" style={{ height: "4rem" }} src={imgUrl2} />
 | 
				
			||||||
 | 
											</a>
 | 
				
			||||||
 | 
										</div>
 | 
				
			||||||
 | 
									)}
 | 
				
			||||||
 | 
								</div>
 | 
				
			||||||
 | 
								<div className="card__footer">{notes ? notes : null}</div>
 | 
				
			||||||
 | 
							</div>
 | 
				
			||||||
 | 
						);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const PlaceholderCard = (): JSX.Element => {
 | 
				
			||||||
 | 
						return (
 | 
				
			||||||
 | 
							<div
 | 
				
			||||||
 | 
								className="card"
 | 
				
			||||||
 | 
								style={{
 | 
				
			||||||
 | 
									width: "100%",
 | 
				
			||||||
 | 
									animation: "pulse 2s infinite",
 | 
				
			||||||
 | 
									transform: "scale(1)",
 | 
				
			||||||
 | 
									display: "flex",
 | 
				
			||||||
 | 
									gap: "1rem",
 | 
				
			||||||
 | 
									padding: "1rem",
 | 
				
			||||||
 | 
								}}
 | 
				
			||||||
 | 
							>
 | 
				
			||||||
 | 
								<div
 | 
				
			||||||
 | 
									style={{
 | 
				
			||||||
 | 
										display: "flex",
 | 
				
			||||||
 | 
										justifyContent: "space-between",
 | 
				
			||||||
 | 
										marginBottom: "1rem",
 | 
				
			||||||
 | 
									}}
 | 
				
			||||||
 | 
								>
 | 
				
			||||||
 | 
									<div
 | 
				
			||||||
 | 
										style={{
 | 
				
			||||||
 | 
											borderRadius: "0.4rem",
 | 
				
			||||||
 | 
											backgroundColor: "gray",
 | 
				
			||||||
 | 
											height: "2rem",
 | 
				
			||||||
 | 
											width: "8rem",
 | 
				
			||||||
 | 
										}}
 | 
				
			||||||
 | 
									/>
 | 
				
			||||||
 | 
									<div
 | 
				
			||||||
 | 
										style={{
 | 
				
			||||||
 | 
											borderRadius: "0.4rem",
 | 
				
			||||||
 | 
											backgroundColor: "gray",
 | 
				
			||||||
 | 
											marginTop: "1rem",
 | 
				
			||||||
 | 
											height: "1rem",
 | 
				
			||||||
 | 
											width: "8rem",
 | 
				
			||||||
 | 
										}}
 | 
				
			||||||
 | 
									/>
 | 
				
			||||||
 | 
								</div>
 | 
				
			||||||
 | 
								<div
 | 
				
			||||||
 | 
									className="card__body"
 | 
				
			||||||
 | 
									style={{
 | 
				
			||||||
 | 
										borderRadius: "0.4rem",
 | 
				
			||||||
 | 
										backgroundColor: "gray",
 | 
				
			||||||
 | 
										height: "3rem",
 | 
				
			||||||
 | 
										display: "flex",
 | 
				
			||||||
 | 
										justifyContent: "center",
 | 
				
			||||||
 | 
										alignItems: "center",
 | 
				
			||||||
 | 
									}}
 | 
				
			||||||
 | 
								/>
 | 
				
			||||||
 | 
								<a className="button disabled button--primary button--block"> </a>
 | 
				
			||||||
 | 
								<div
 | 
				
			||||||
 | 
									style={{
 | 
				
			||||||
 | 
										borderRadius: "0.4rem",
 | 
				
			||||||
 | 
										backgroundColor: "gray",
 | 
				
			||||||
 | 
										width: "8rem",
 | 
				
			||||||
 | 
										height: "2rem",
 | 
				
			||||||
 | 
									}}
 | 
				
			||||||
 | 
								/>
 | 
				
			||||||
 | 
								<div
 | 
				
			||||||
 | 
									style={{
 | 
				
			||||||
 | 
										borderRadius: "0.4rem",
 | 
				
			||||||
 | 
										backgroundColor: "gray",
 | 
				
			||||||
 | 
										width: "11rem",
 | 
				
			||||||
 | 
										height: "1rem",
 | 
				
			||||||
 | 
									}}
 | 
				
			||||||
 | 
								/>
 | 
				
			||||||
 | 
								<div
 | 
				
			||||||
 | 
									style={{
 | 
				
			||||||
 | 
										borderRadius: "0.4rem",
 | 
				
			||||||
 | 
										backgroundColor: "gray",
 | 
				
			||||||
 | 
										width: "9rem",
 | 
				
			||||||
 | 
										height: "1rem",
 | 
				
			||||||
 | 
									}}
 | 
				
			||||||
 | 
								/>
 | 
				
			||||||
 | 
								<div
 | 
				
			||||||
 | 
									style={{
 | 
				
			||||||
 | 
										borderRadius: "0.4rem",
 | 
				
			||||||
 | 
										backgroundColor: "gray",
 | 
				
			||||||
 | 
										width: "13rem",
 | 
				
			||||||
 | 
										height: "1rem",
 | 
				
			||||||
 | 
									}}
 | 
				
			||||||
 | 
								/>
 | 
				
			||||||
 | 
								<div
 | 
				
			||||||
 | 
									style={{
 | 
				
			||||||
 | 
										borderRadius: "0.4rem",
 | 
				
			||||||
 | 
										backgroundColor: "gray",
 | 
				
			||||||
 | 
										width: "11rem",
 | 
				
			||||||
 | 
										height: "1rem",
 | 
				
			||||||
 | 
									}}
 | 
				
			||||||
 | 
								/>
 | 
				
			||||||
 | 
							</div>
 | 
				
			||||||
 | 
						);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
							
								
								
									
										151
									
								
								src/pages/downloads/_components/FirmwareCard.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,151 @@
 | 
				
			|||||||
 | 
					import React from "react";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { DeviceFirmwareResource } from "../../../utils/apiTypes";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export interface releaseCardProps {
 | 
				
			||||||
 | 
						variant: string;
 | 
				
			||||||
 | 
						description: string;
 | 
				
			||||||
 | 
						release?: DeviceFirmwareResource[];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const FirmwareCard = ({
 | 
				
			||||||
 | 
						variant,
 | 
				
			||||||
 | 
						description,
 | 
				
			||||||
 | 
						release,
 | 
				
			||||||
 | 
					}: releaseCardProps): JSX.Element => {
 | 
				
			||||||
 | 
						return (
 | 
				
			||||||
 | 
							<div className="card m-4 border-2 border-secondary">
 | 
				
			||||||
 | 
								<div
 | 
				
			||||||
 | 
									className="card__header"
 | 
				
			||||||
 | 
									style={{ display: "flex", justifyContent: "space-between" }}
 | 
				
			||||||
 | 
								>
 | 
				
			||||||
 | 
									<h3>{variant}</h3>
 | 
				
			||||||
 | 
									{release?.length && (
 | 
				
			||||||
 | 
										<a href={release[0].page_url}>{release[0].title}</a>
 | 
				
			||||||
 | 
									)}
 | 
				
			||||||
 | 
								</div>
 | 
				
			||||||
 | 
								<div className="card__body">
 | 
				
			||||||
 | 
									<p>{description}</p>
 | 
				
			||||||
 | 
								</div>
 | 
				
			||||||
 | 
								<div className="card__footer mt-auto">
 | 
				
			||||||
 | 
									<div className="margin-top--sm">
 | 
				
			||||||
 | 
										<details>
 | 
				
			||||||
 | 
											<summary>Older Versions</summary>
 | 
				
			||||||
 | 
											{release.slice(1, 6).map((release) => {
 | 
				
			||||||
 | 
												return (
 | 
				
			||||||
 | 
													<div key={release.id}>
 | 
				
			||||||
 | 
														<a href={release.zip_url}>{release.title}</a>
 | 
				
			||||||
 | 
													</div>
 | 
				
			||||||
 | 
												);
 | 
				
			||||||
 | 
											})}
 | 
				
			||||||
 | 
										</details>
 | 
				
			||||||
 | 
									</div>
 | 
				
			||||||
 | 
									{release?.length ? (
 | 
				
			||||||
 | 
										<>
 | 
				
			||||||
 | 
											<a
 | 
				
			||||||
 | 
												href={release[0].zip_url}
 | 
				
			||||||
 | 
												className="button button--secondary button--block margin-top--sm"
 | 
				
			||||||
 | 
											>
 | 
				
			||||||
 | 
												Download {variant}
 | 
				
			||||||
 | 
											</a>
 | 
				
			||||||
 | 
										</>
 | 
				
			||||||
 | 
									) : (
 | 
				
			||||||
 | 
										<button disabled className="button button--secondary button--block">
 | 
				
			||||||
 | 
											Loading...
 | 
				
			||||||
 | 
										</button>
 | 
				
			||||||
 | 
									)}
 | 
				
			||||||
 | 
								</div>
 | 
				
			||||||
 | 
							</div>
 | 
				
			||||||
 | 
						);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const PlaceholderFirmwareCard = (): JSX.Element => {
 | 
				
			||||||
 | 
						return (
 | 
				
			||||||
 | 
							<div
 | 
				
			||||||
 | 
								className="card"
 | 
				
			||||||
 | 
								style={{
 | 
				
			||||||
 | 
									width: "100%",
 | 
				
			||||||
 | 
									animation: "pulse 2s infinite",
 | 
				
			||||||
 | 
									transform: "scale(1)",
 | 
				
			||||||
 | 
									display: "flex",
 | 
				
			||||||
 | 
									gap: "1rem",
 | 
				
			||||||
 | 
									padding: "1rem",
 | 
				
			||||||
 | 
								}}
 | 
				
			||||||
 | 
							>
 | 
				
			||||||
 | 
								<div
 | 
				
			||||||
 | 
									style={{
 | 
				
			||||||
 | 
										display: "flex",
 | 
				
			||||||
 | 
										justifyContent: "space-between",
 | 
				
			||||||
 | 
										marginBottom: "1rem",
 | 
				
			||||||
 | 
									}}
 | 
				
			||||||
 | 
								>
 | 
				
			||||||
 | 
									<div
 | 
				
			||||||
 | 
										style={{
 | 
				
			||||||
 | 
											borderRadius: "0.4rem",
 | 
				
			||||||
 | 
											backgroundColor: "gray",
 | 
				
			||||||
 | 
											height: "2rem",
 | 
				
			||||||
 | 
											width: "8rem",
 | 
				
			||||||
 | 
										}}
 | 
				
			||||||
 | 
									/>
 | 
				
			||||||
 | 
									<div
 | 
				
			||||||
 | 
										style={{
 | 
				
			||||||
 | 
											borderRadius: "0.4rem",
 | 
				
			||||||
 | 
											backgroundColor: "gray",
 | 
				
			||||||
 | 
											marginTop: "1rem",
 | 
				
			||||||
 | 
											height: "1rem",
 | 
				
			||||||
 | 
											width: "8rem",
 | 
				
			||||||
 | 
										}}
 | 
				
			||||||
 | 
									/>
 | 
				
			||||||
 | 
								</div>
 | 
				
			||||||
 | 
								<div
 | 
				
			||||||
 | 
									className="card__body"
 | 
				
			||||||
 | 
									style={{
 | 
				
			||||||
 | 
										borderRadius: "0.4rem",
 | 
				
			||||||
 | 
										backgroundColor: "gray",
 | 
				
			||||||
 | 
										height: "3rem",
 | 
				
			||||||
 | 
									}}
 | 
				
			||||||
 | 
								/>
 | 
				
			||||||
 | 
								<a className="button disabled button--primary button--block"> </a>
 | 
				
			||||||
 | 
								<div
 | 
				
			||||||
 | 
									style={{
 | 
				
			||||||
 | 
										borderRadius: "0.4rem",
 | 
				
			||||||
 | 
										backgroundColor: "gray",
 | 
				
			||||||
 | 
										width: "8rem",
 | 
				
			||||||
 | 
										height: "2rem",
 | 
				
			||||||
 | 
									}}
 | 
				
			||||||
 | 
								/>
 | 
				
			||||||
 | 
								<div
 | 
				
			||||||
 | 
									style={{
 | 
				
			||||||
 | 
										borderRadius: "0.4rem",
 | 
				
			||||||
 | 
										backgroundColor: "gray",
 | 
				
			||||||
 | 
										width: "11rem",
 | 
				
			||||||
 | 
										height: "1rem",
 | 
				
			||||||
 | 
									}}
 | 
				
			||||||
 | 
								/>
 | 
				
			||||||
 | 
								<div
 | 
				
			||||||
 | 
									style={{
 | 
				
			||||||
 | 
										borderRadius: "0.4rem",
 | 
				
			||||||
 | 
										backgroundColor: "gray",
 | 
				
			||||||
 | 
										width: "9rem",
 | 
				
			||||||
 | 
										height: "1rem",
 | 
				
			||||||
 | 
									}}
 | 
				
			||||||
 | 
								/>
 | 
				
			||||||
 | 
								<div
 | 
				
			||||||
 | 
									style={{
 | 
				
			||||||
 | 
										borderRadius: "0.4rem",
 | 
				
			||||||
 | 
										backgroundColor: "gray",
 | 
				
			||||||
 | 
										width: "13rem",
 | 
				
			||||||
 | 
										height: "1rem",
 | 
				
			||||||
 | 
									}}
 | 
				
			||||||
 | 
								/>
 | 
				
			||||||
 | 
								<div
 | 
				
			||||||
 | 
									style={{
 | 
				
			||||||
 | 
										borderRadius: "0.4rem",
 | 
				
			||||||
 | 
										backgroundColor: "gray",
 | 
				
			||||||
 | 
										width: "11rem",
 | 
				
			||||||
 | 
										height: "1rem",
 | 
				
			||||||
 | 
									}}
 | 
				
			||||||
 | 
								/>
 | 
				
			||||||
 | 
							</div>
 | 
				
			||||||
 | 
						);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
							
								
								
									
										18
									
								
								src/pages/downloads/_components/HeaderText.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,18 @@
 | 
				
			|||||||
 | 
					import React from "react";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const HeaderText = ({ type, text, link }): JSX.Element => {
 | 
				
			||||||
 | 
						const Header = type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return (
 | 
				
			||||||
 | 
							<Header className="anchor anchorWithHideOnScrollNavbar_node_modules-@docusaurus-theme-classic-lib-next-theme-Heading-styles-module">
 | 
				
			||||||
 | 
								{text}
 | 
				
			||||||
 | 
								{link && (
 | 
				
			||||||
 | 
									<a
 | 
				
			||||||
 | 
										className="hash-link"
 | 
				
			||||||
 | 
										href={`#${link}`}
 | 
				
			||||||
 | 
										title="Direct link to heading"
 | 
				
			||||||
 | 
									/>
 | 
				
			||||||
 | 
								)}
 | 
				
			||||||
 | 
							</Header>
 | 
				
			||||||
 | 
						);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
							
								
								
									
										288
									
								
								src/pages/downloads/index.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,288 @@
 | 
				
			|||||||
 | 
					import React from "react";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { FaAndroid, FaApple } from "react-icons/fa";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import useBaseUrl from "@docusaurus/useBaseUrl";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import {
 | 
				
			||||||
 | 
						ArrowTopRightOnSquareIcon,
 | 
				
			||||||
 | 
						ComputerDesktopIcon,
 | 
				
			||||||
 | 
						GlobeAltIcon,
 | 
				
			||||||
 | 
					} from "@heroicons/react/24/solid";
 | 
				
			||||||
 | 
					import Layout from "@theme/Layout";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const Firmware = (): JSX.Element => {
 | 
				
			||||||
 | 
						return (
 | 
				
			||||||
 | 
							<Layout
 | 
				
			||||||
 | 
								title="Завантаження"
 | 
				
			||||||
 | 
								description="Клієнти для наших сервісів для різних платформ."
 | 
				
			||||||
 | 
							>
 | 
				
			||||||
 | 
								<div className="container mt-8 flex flex-col gap-3">
 | 
				
			||||||
 | 
									<div className="flex w-full overflow-hidden rounded-xl">
 | 
				
			||||||
 | 
										<div className="flex w-1/5 bg-gradient-to-r from-rose-500 to-primary">
 | 
				
			||||||
 | 
											<span className="m-auto h-20 text-4xl font-black">#IRC</span>
 | 
				
			||||||
 | 
										</div>
 | 
				
			||||||
 | 
										<div className="flex w-full columns-3 flex-col bg-primary lg:flex-row">
 | 
				
			||||||
 | 
											<div className="card m-4 border-2 border-secondary">
 | 
				
			||||||
 | 
												<div className="card__header">
 | 
				
			||||||
 | 
													<h3>Apple</h3>
 | 
				
			||||||
 | 
												</div>
 | 
				
			||||||
 | 
												<div className="card__body flex items-center">
 | 
				
			||||||
 | 
													<div className="m-auto">
 | 
				
			||||||
 | 
														<FaApple className="h-20 w-20" />
 | 
				
			||||||
 | 
													</div>
 | 
				
			||||||
 | 
												</div>
 | 
				
			||||||
 | 
												<div className="card__body">
 | 
				
			||||||
 | 
													Available on MacOS & iOS. Requires MacOS Ventura or iOS 16+.
 | 
				
			||||||
 | 
												</div>
 | 
				
			||||||
 | 
												<div className="card__footer mt-auto">
 | 
				
			||||||
 | 
													<a
 | 
				
			||||||
 | 
														target="_blank"
 | 
				
			||||||
 | 
														rel="noopener noreferrer"
 | 
				
			||||||
 | 
														href="#"
 | 
				
			||||||
 | 
														className="m-auto flex rounded-lg border-4 border-transparent bg-accent p-1 font-semibold text-black shadow-md hover:text-black hover:brightness-110 active:border-green-200"
 | 
				
			||||||
 | 
													>
 | 
				
			||||||
 | 
														App Store
 | 
				
			||||||
 | 
														<ArrowTopRightOnSquareIcon className="m-auto ml-2 h-4" />
 | 
				
			||||||
 | 
													</a>
 | 
				
			||||||
 | 
												</div>
 | 
				
			||||||
 | 
											</div>
 | 
				
			||||||
 | 
											<div className="card m-4 border-2 border-secondary">
 | 
				
			||||||
 | 
												<div className="card__header">
 | 
				
			||||||
 | 
													<h3>Android</h3>
 | 
				
			||||||
 | 
												</div>
 | 
				
			||||||
 | 
												<div className="card__body flex items-center">
 | 
				
			||||||
 | 
													<div className="m-auto">
 | 
				
			||||||
 | 
														<FaAndroid className="h-20 w-20" />
 | 
				
			||||||
 | 
													</div>
 | 
				
			||||||
 | 
												</div>
 | 
				
			||||||
 | 
												<div className="card__body">Sideloading also available.</div>
 | 
				
			||||||
 | 
												<div className="card__footer mt-auto">
 | 
				
			||||||
 | 
													<a
 | 
				
			||||||
 | 
														target="_blank"
 | 
				
			||||||
 | 
														rel="noopener noreferrer"
 | 
				
			||||||
 | 
														href="#"
 | 
				
			||||||
 | 
														className="m-auto flex rounded-lg border-4 border-transparent bg-accent p-1 font-semibold text-black shadow-md hover:text-black hover:brightness-110 active:border-green-200"
 | 
				
			||||||
 | 
													>
 | 
				
			||||||
 | 
														F-Droid
 | 
				
			||||||
 | 
														<ArrowTopRightOnSquareIcon className="m-auto ml-2 h-4" />
 | 
				
			||||||
 | 
													</a>
 | 
				
			||||||
 | 
													<a
 | 
				
			||||||
 | 
														target="_blank"
 | 
				
			||||||
 | 
														rel="noopener noreferrer"
 | 
				
			||||||
 | 
														href="#"
 | 
				
			||||||
 | 
														className="mt-4 flex rounded-lg border-4 border-transparent bg-accent p-1 font-semibold text-black shadow-md hover:text-black hover:brightness-110 active:border-green-200"
 | 
				
			||||||
 | 
													>
 | 
				
			||||||
 | 
														Play Store
 | 
				
			||||||
 | 
														<ArrowTopRightOnSquareIcon className="m-auto ml-2 h-4" />
 | 
				
			||||||
 | 
													</a>
 | 
				
			||||||
 | 
												</div>
 | 
				
			||||||
 | 
											</div>
 | 
				
			||||||
 | 
											<div className="card m-4 border-2 border-secondary">
 | 
				
			||||||
 | 
												<div className="card__header">
 | 
				
			||||||
 | 
													<h3>Web</h3>
 | 
				
			||||||
 | 
												</div>
 | 
				
			||||||
 | 
												<div className="card__body flex items-center">
 | 
				
			||||||
 | 
													<div className="m-auto">
 | 
				
			||||||
 | 
														<GlobeAltIcon className="h-20 w-20" />
 | 
				
			||||||
 | 
													</div>
 | 
				
			||||||
 | 
												</div>
 | 
				
			||||||
 | 
												<div className="card__body">
 | 
				
			||||||
 | 
													<a href="https://sr.ht/~emersion/gamja/">gamja</a> веб клієнт
 | 
				
			||||||
 | 
													для IRC.
 | 
				
			||||||
 | 
												</div>
 | 
				
			||||||
 | 
												<div className="card__footer mt-auto">
 | 
				
			||||||
 | 
													<a
 | 
				
			||||||
 | 
														target="_blank"
 | 
				
			||||||
 | 
														rel="noopener noreferrer"
 | 
				
			||||||
 | 
														href="https://irc.dead.guru"
 | 
				
			||||||
 | 
														className="m-auto flex rounded-lg border-4 border-transparent bg-accent p-1 font-semibold text-black shadow-md hover:text-black hover:brightness-110 active:border-green-200"
 | 
				
			||||||
 | 
													>
 | 
				
			||||||
 | 
														irc.dead.guru
 | 
				
			||||||
 | 
														<ArrowTopRightOnSquareIcon className="m-auto ml-2 h-4" />
 | 
				
			||||||
 | 
													</a>
 | 
				
			||||||
 | 
												</div>
 | 
				
			||||||
 | 
											</div>
 | 
				
			||||||
 | 
										</div>
 | 
				
			||||||
 | 
									</div>
 | 
				
			||||||
 | 
									{/*  */}
 | 
				
			||||||
 | 
									<div className="flex w-full overflow-hidden rounded-xl">
 | 
				
			||||||
 | 
										<div className="flex w-1/5 bg-gradient-to-r from-green-500 to-primary">
 | 
				
			||||||
 | 
											<span className="m-auto h-20 text-4xl font-black">#MATRIX</span>
 | 
				
			||||||
 | 
										</div>
 | 
				
			||||||
 | 
										<div className="flex w-full columns-3 flex-col bg-primary lg:flex-row">
 | 
				
			||||||
 | 
											<div className="card m-4 border-2 border-secondary">
 | 
				
			||||||
 | 
												<div className="card__header">
 | 
				
			||||||
 | 
													<h3>Apple</h3>
 | 
				
			||||||
 | 
												</div>
 | 
				
			||||||
 | 
												<div className="card__body flex items-center">
 | 
				
			||||||
 | 
													<div className="m-auto">
 | 
				
			||||||
 | 
														<FaApple className="h-20 w-20" />
 | 
				
			||||||
 | 
													</div>
 | 
				
			||||||
 | 
												</div>
 | 
				
			||||||
 | 
												<div className="card__body">
 | 
				
			||||||
 | 
													Available on MacOS & iOS. Requires MacOS Ventura or iOS 16+.
 | 
				
			||||||
 | 
												</div>
 | 
				
			||||||
 | 
												<div className="card__footer mt-auto">
 | 
				
			||||||
 | 
													<a
 | 
				
			||||||
 | 
														target="_blank"
 | 
				
			||||||
 | 
														rel="noopener noreferrer"
 | 
				
			||||||
 | 
														href="#"
 | 
				
			||||||
 | 
														className="m-auto flex rounded-lg border-4 border-transparent bg-accent p-1 font-semibold text-black shadow-md hover:text-black hover:brightness-110 active:border-green-200"
 | 
				
			||||||
 | 
													>
 | 
				
			||||||
 | 
														App Store
 | 
				
			||||||
 | 
														<ArrowTopRightOnSquareIcon className="m-auto ml-2 h-4" />
 | 
				
			||||||
 | 
													</a>
 | 
				
			||||||
 | 
												</div>
 | 
				
			||||||
 | 
											</div>
 | 
				
			||||||
 | 
											<div className="card m-4 border-2 border-secondary">
 | 
				
			||||||
 | 
												<div className="card__header">
 | 
				
			||||||
 | 
													<h3>Android</h3>
 | 
				
			||||||
 | 
												</div>
 | 
				
			||||||
 | 
												<div className="card__body flex items-center">
 | 
				
			||||||
 | 
													<div className="m-auto">
 | 
				
			||||||
 | 
														<FaAndroid className="h-20 w-20" />
 | 
				
			||||||
 | 
													</div>
 | 
				
			||||||
 | 
												</div>
 | 
				
			||||||
 | 
												<div className="card__body">Sideloading also available.</div>
 | 
				
			||||||
 | 
												<div className="card__footer mt-auto">
 | 
				
			||||||
 | 
													<a
 | 
				
			||||||
 | 
														target="_blank"
 | 
				
			||||||
 | 
														rel="noopener noreferrer"
 | 
				
			||||||
 | 
														href="#"
 | 
				
			||||||
 | 
														className="m-auto flex rounded-lg border-4 border-transparent bg-accent p-1 font-semibold text-black shadow-md hover:text-black hover:brightness-110 active:border-green-200"
 | 
				
			||||||
 | 
													>
 | 
				
			||||||
 | 
														F-Droid
 | 
				
			||||||
 | 
														<ArrowTopRightOnSquareIcon className="m-auto ml-2 h-4" />
 | 
				
			||||||
 | 
													</a>
 | 
				
			||||||
 | 
													<a
 | 
				
			||||||
 | 
														target="_blank"
 | 
				
			||||||
 | 
														rel="noopener noreferrer"
 | 
				
			||||||
 | 
														href="#"
 | 
				
			||||||
 | 
														className="mt-4 flex rounded-lg border-4 border-transparent bg-accent p-1 font-semibold text-black shadow-md hover:text-black hover:brightness-110 active:border-green-200"
 | 
				
			||||||
 | 
													>
 | 
				
			||||||
 | 
														Play Store
 | 
				
			||||||
 | 
														<ArrowTopRightOnSquareIcon className="m-auto ml-2 h-4" />
 | 
				
			||||||
 | 
													</a>
 | 
				
			||||||
 | 
												</div>
 | 
				
			||||||
 | 
											</div>
 | 
				
			||||||
 | 
											<div className="card m-4 border-2 border-secondary">
 | 
				
			||||||
 | 
												<div className="card__header">
 | 
				
			||||||
 | 
													<h3>Web</h3>
 | 
				
			||||||
 | 
												</div>
 | 
				
			||||||
 | 
												<div className="card__body flex items-center">
 | 
				
			||||||
 | 
													<div className="m-auto">
 | 
				
			||||||
 | 
														<GlobeAltIcon className="h-20 w-20" />
 | 
				
			||||||
 | 
													</div>
 | 
				
			||||||
 | 
												</div>
 | 
				
			||||||
 | 
												<div className="card__body">
 | 
				
			||||||
 | 
													fluffychat веб клієнт для matrix.
 | 
				
			||||||
 | 
												</div>
 | 
				
			||||||
 | 
												<div className="card__footer mt-auto">
 | 
				
			||||||
 | 
													<a
 | 
				
			||||||
 | 
														target="_blank"
 | 
				
			||||||
 | 
														rel="noopener noreferrer"
 | 
				
			||||||
 | 
														href="https://xmpp.dead.guru:5281/conversejs"
 | 
				
			||||||
 | 
														className="m-auto flex rounded-lg border-4 border-transparent bg-accent p-1 font-semibold text-black shadow-md hover:text-black hover:brightness-110 active:border-green-200"
 | 
				
			||||||
 | 
													>
 | 
				
			||||||
 | 
														https://fluffychat.im/
 | 
				
			||||||
 | 
														<ArrowTopRightOnSquareIcon className="m-auto ml-2 h-4" />
 | 
				
			||||||
 | 
													</a>
 | 
				
			||||||
 | 
												</div>
 | 
				
			||||||
 | 
											</div>
 | 
				
			||||||
 | 
										</div>
 | 
				
			||||||
 | 
									</div>
 | 
				
			||||||
 | 
									{/*  */}
 | 
				
			||||||
 | 
									<div className="flex w-full overflow-hidden rounded-xl">
 | 
				
			||||||
 | 
										<div className="flex w-1/5 bg-gradient-to-r from-yellow-500 to-primary">
 | 
				
			||||||
 | 
											<span className="m-auto h-20 text-4xl font-black">#XMPP</span>
 | 
				
			||||||
 | 
										</div>
 | 
				
			||||||
 | 
										<div className="flex w-full columns-3 flex-col bg-primary lg:flex-row">
 | 
				
			||||||
 | 
											<div className="card m-4 border-2 border-secondary">
 | 
				
			||||||
 | 
												<div className="card__header">
 | 
				
			||||||
 | 
													<h3>Apple</h3>
 | 
				
			||||||
 | 
												</div>
 | 
				
			||||||
 | 
												<div className="card__body flex items-center">
 | 
				
			||||||
 | 
													<div className="m-auto">
 | 
				
			||||||
 | 
														<FaApple className="h-20 w-20" />
 | 
				
			||||||
 | 
													</div>
 | 
				
			||||||
 | 
												</div>
 | 
				
			||||||
 | 
												<div className="card__body">
 | 
				
			||||||
 | 
													Available on MacOS & iOS. Requires MacOS Ventura or iOS 16+.
 | 
				
			||||||
 | 
												</div>
 | 
				
			||||||
 | 
												<div className="card__footer mt-auto">
 | 
				
			||||||
 | 
													<a
 | 
				
			||||||
 | 
														target="_blank"
 | 
				
			||||||
 | 
														rel="noopener noreferrer"
 | 
				
			||||||
 | 
														href="#"
 | 
				
			||||||
 | 
														className="m-auto flex rounded-lg border-4 border-transparent bg-accent p-1 font-semibold text-black shadow-md hover:text-black hover:brightness-110 active:border-green-200"
 | 
				
			||||||
 | 
													>
 | 
				
			||||||
 | 
														App Store
 | 
				
			||||||
 | 
														<ArrowTopRightOnSquareIcon className="m-auto ml-2 h-4" />
 | 
				
			||||||
 | 
													</a>
 | 
				
			||||||
 | 
												</div>
 | 
				
			||||||
 | 
											</div>
 | 
				
			||||||
 | 
											<div className="card m-4 border-2 border-secondary">
 | 
				
			||||||
 | 
												<div className="card__header">
 | 
				
			||||||
 | 
													<h3>Android</h3>
 | 
				
			||||||
 | 
												</div>
 | 
				
			||||||
 | 
												<div className="card__body flex items-center">
 | 
				
			||||||
 | 
													<div className="m-auto">
 | 
				
			||||||
 | 
														<FaAndroid className="h-20 w-20" />
 | 
				
			||||||
 | 
													</div>
 | 
				
			||||||
 | 
												</div>
 | 
				
			||||||
 | 
												<div className="card__body">Sideloading also available.</div>
 | 
				
			||||||
 | 
												<div className="card__footer mt-auto">
 | 
				
			||||||
 | 
													<a
 | 
				
			||||||
 | 
														target="_blank"
 | 
				
			||||||
 | 
														rel="noopener noreferrer"
 | 
				
			||||||
 | 
														href="#"
 | 
				
			||||||
 | 
														className="m-auto flex rounded-lg border-4 border-transparent bg-accent p-1 font-semibold text-black shadow-md hover:text-black hover:brightness-110 active:border-green-200"
 | 
				
			||||||
 | 
													>
 | 
				
			||||||
 | 
														F-Droid
 | 
				
			||||||
 | 
														<ArrowTopRightOnSquareIcon className="m-auto ml-2 h-4" />
 | 
				
			||||||
 | 
													</a>
 | 
				
			||||||
 | 
													<a
 | 
				
			||||||
 | 
														target="_blank"
 | 
				
			||||||
 | 
														rel="noopener noreferrer"
 | 
				
			||||||
 | 
														href="#"
 | 
				
			||||||
 | 
														className="mt-4 flex rounded-lg border-4 border-transparent bg-accent p-1 font-semibold text-black shadow-md hover:text-black hover:brightness-110 active:border-green-200"
 | 
				
			||||||
 | 
													>
 | 
				
			||||||
 | 
														Play Store
 | 
				
			||||||
 | 
														<ArrowTopRightOnSquareIcon className="m-auto ml-2 h-4" />
 | 
				
			||||||
 | 
													</a>
 | 
				
			||||||
 | 
												</div>
 | 
				
			||||||
 | 
											</div>
 | 
				
			||||||
 | 
											<div className="card m-4 border-2 border-secondary">
 | 
				
			||||||
 | 
												<div className="card__header">
 | 
				
			||||||
 | 
													<h3>Web</h3>
 | 
				
			||||||
 | 
												</div>
 | 
				
			||||||
 | 
												<div className="card__body flex items-center">
 | 
				
			||||||
 | 
													<div className="m-auto">
 | 
				
			||||||
 | 
														<GlobeAltIcon className="h-20 w-20" />
 | 
				
			||||||
 | 
													</div>
 | 
				
			||||||
 | 
												</div>
 | 
				
			||||||
 | 
												<div className="card__body">
 | 
				
			||||||
 | 
													<a href="https://conversejs.org/">Converse.js</a> веб клієнт для
 | 
				
			||||||
 | 
													XMPP.
 | 
				
			||||||
 | 
												</div>
 | 
				
			||||||
 | 
												<div className="card__footer mt-auto">
 | 
				
			||||||
 | 
													<a
 | 
				
			||||||
 | 
														target="_blank"
 | 
				
			||||||
 | 
														rel="noopener noreferrer"
 | 
				
			||||||
 | 
														href="https://xmpp.dead.guru:5281/conversejs"
 | 
				
			||||||
 | 
														className="m-auto flex rounded-lg border-4 border-transparent bg-accent p-1 font-semibold text-black shadow-md hover:text-black hover:brightness-110 active:border-green-200"
 | 
				
			||||||
 | 
													>
 | 
				
			||||||
 | 
														https://xmpp.dead.guru:5281/conversejs
 | 
				
			||||||
 | 
														<ArrowTopRightOnSquareIcon className="m-auto ml-2 h-4" />
 | 
				
			||||||
 | 
													</a>
 | 
				
			||||||
 | 
												</div>
 | 
				
			||||||
 | 
											</div>
 | 
				
			||||||
 | 
										</div>
 | 
				
			||||||
 | 
									</div>
 | 
				
			||||||
 | 
								</div>
 | 
				
			||||||
 | 
							</Layout>
 | 
				
			||||||
 | 
						);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default Firmware;
 | 
				
			||||||
							
								
								
									
										7
									
								
								src/pages/e/index.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,7 @@
 | 
				
			|||||||
 | 
					---
 | 
				
			||||||
 | 
					id: e
 | 
				
			||||||
 | 
					title: Dead Channel Settings
 | 
				
			||||||
 | 
					sidebar_label: e
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## TBD
 | 
				
			||||||
							
								
								
									
										300
									
								
								src/pages/index.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,300 @@
 | 
				
			|||||||
 | 
					import "react-responsive-carousel/lib/styles/carousel.min.css"; // requires a loader
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import React from "react";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { Carousel } from "react-responsive-carousel";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import Head from "@docusaurus/Head";
 | 
				
			||||||
 | 
					import Link from "@docusaurus/Link";
 | 
				
			||||||
 | 
					import useBaseUrl from "@docusaurus/useBaseUrl";
 | 
				
			||||||
 | 
					import useDocusaurusContext from "@docusaurus/useDocusaurusContext";
 | 
				
			||||||
 | 
					import Layout from "@theme/Layout";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { SocialCard, SocialCardProps } from "../components/homepage/SocialCard";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const features = [
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							title: "Основа мережі — Спілкування",
 | 
				
			||||||
 | 
							imageUrl: "img/homepage/messages.svg",
 | 
				
			||||||
 | 
							description: (
 | 
				
			||||||
 | 
								<>
 | 
				
			||||||
 | 
									Мережу в першу чергу, створюють люди, а не технології. Спілкування
 | 
				
			||||||
 | 
									дозволяє нам зберігати зв'язок з друзями та родиною, а також будувати
 | 
				
			||||||
 | 
									новий, цікавий і вільний світ.
 | 
				
			||||||
 | 
								</>
 | 
				
			||||||
 | 
							),
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							title: "Захист",
 | 
				
			||||||
 | 
							imageUrl: "img/homepage/encryption.svg",
 | 
				
			||||||
 | 
							description: (
 | 
				
			||||||
 | 
								<>
 | 
				
			||||||
 | 
									Ми намагаємося захистити вашу приватність, використовуючи шифрування де
 | 
				
			||||||
 | 
									це можливо та необхідно. Ви можете використовувати власні ключі
 | 
				
			||||||
 | 
									шифрування, щоб забезпечити максимальний рівень захисту. Ми також
 | 
				
			||||||
 | 
									відкриті для аудиту та вдосконалення наших методів шифрування та
 | 
				
			||||||
 | 
									захисту.
 | 
				
			||||||
 | 
								</>
 | 
				
			||||||
 | 
							),
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							title: "Незалежність",
 | 
				
			||||||
 | 
							imageUrl: "img/homepage/platforms.svg",
 | 
				
			||||||
 | 
							description: (
 | 
				
			||||||
 | 
								<>
 | 
				
			||||||
 | 
									Свобода спілкування не повинна бути обмежена. Ми намагаємося
 | 
				
			||||||
 | 
									підтримувати якомога більше платформ, щоб ви могли спілкуватися з
 | 
				
			||||||
 | 
									друзями та родиною, незалежно від того, який пристрій ви використовуєте.
 | 
				
			||||||
 | 
								</>
 | 
				
			||||||
 | 
							),
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							title: "Open Source",
 | 
				
			||||||
 | 
							imageUrl: "img/homepage/opensource.svg",
 | 
				
			||||||
 | 
							description: (
 | 
				
			||||||
 | 
								<>
 | 
				
			||||||
 | 
									Мережа побудована на основі відкритих проектів, що дозволяє вам приймати
 | 
				
			||||||
 | 
									участь в розвитку та вдосконаленні мережі.
 | 
				
			||||||
 | 
								</>
 | 
				
			||||||
 | 
							),
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
					];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const SocialCards: SocialCardProps[] = [
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							color: "bg-[#3875EA]",
 | 
				
			||||||
 | 
							link: "https://irc.dead.guru",
 | 
				
			||||||
 | 
							children: (
 | 
				
			||||||
 | 
								<img alt="irc" className="m-auto h-10" src="/img/services/irc.svg" />
 | 
				
			||||||
 | 
							),
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							color: "bg-[#FFFFFF]",
 | 
				
			||||||
 | 
							link: "https://matrix.to/#/#adhd_lab:hypogea.org",
 | 
				
			||||||
 | 
							children: (
 | 
				
			||||||
 | 
								<img
 | 
				
			||||||
 | 
									alt="matrix"
 | 
				
			||||||
 | 
									className="m-auto h-14"
 | 
				
			||||||
 | 
									src="/img/services/Matrix_logo.svg"
 | 
				
			||||||
 | 
								/>
 | 
				
			||||||
 | 
							),
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							color: "bg-[#95c0d9]",
 | 
				
			||||||
 | 
							link: "https://xmpp.dead.guru:5281/",
 | 
				
			||||||
 | 
							children: (
 | 
				
			||||||
 | 
								<img
 | 
				
			||||||
 | 
									alt="xmpp"
 | 
				
			||||||
 | 
									className="m-auto h-14"
 | 
				
			||||||
 | 
									src="/img/services/XMPP_logo.svg"
 | 
				
			||||||
 | 
								/>
 | 
				
			||||||
 | 
							),
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							color: "bg-[#f05539]",
 | 
				
			||||||
 | 
							link: "https://git.dead.guru/",
 | 
				
			||||||
 | 
							children: (
 | 
				
			||||||
 | 
								<img alt="git" className="m-auto h-14" src="/img/services/git_logo.svg" />
 | 
				
			||||||
 | 
							),
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							color: "bg-[#9e9b9a]",
 | 
				
			||||||
 | 
							link: "https://mine.dead.guru",
 | 
				
			||||||
 | 
							children: (
 | 
				
			||||||
 | 
								<img
 | 
				
			||||||
 | 
									alt="minecraft"
 | 
				
			||||||
 | 
									className="m-auto h-16"
 | 
				
			||||||
 | 
									src="/img/services/minecraft_logo.svg"
 | 
				
			||||||
 | 
								/>
 | 
				
			||||||
 | 
							),
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							color: "bg-[#39322b]",
 | 
				
			||||||
 | 
							link: "https://bookhouse.hypogea.org/",
 | 
				
			||||||
 | 
							children: (
 | 
				
			||||||
 | 
								<img
 | 
				
			||||||
 | 
									alt="Calibre"
 | 
				
			||||||
 | 
									className="m-auto h-12"
 | 
				
			||||||
 | 
									src="/img/services/Calibre_logo.png"
 | 
				
			||||||
 | 
								/>
 | 
				
			||||||
 | 
							),
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							color: "bg-[#6366f1]",
 | 
				
			||||||
 | 
							link: "https://pi.dead.guru",
 | 
				
			||||||
 | 
							children: (
 | 
				
			||||||
 | 
								<img
 | 
				
			||||||
 | 
									alt="reddit"
 | 
				
			||||||
 | 
									className="m-auto h-20"
 | 
				
			||||||
 | 
									src="/img/services/Pixelfed_logo.svg"
 | 
				
			||||||
 | 
								/>
 | 
				
			||||||
 | 
							),
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
					];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function Home() {
 | 
				
			||||||
 | 
						const context = useDocusaurusContext();
 | 
				
			||||||
 | 
						const { siteConfig } = context;
 | 
				
			||||||
 | 
						return (
 | 
				
			||||||
 | 
							<Layout>
 | 
				
			||||||
 | 
								<Head>
 | 
				
			||||||
 | 
									<meta property="og:title" content="Dead Network" />
 | 
				
			||||||
 | 
									<meta
 | 
				
			||||||
 | 
										property="og:image"
 | 
				
			||||||
 | 
										content="https://meshtastic.org/design/web/social-preview-1200x630.png"
 | 
				
			||||||
 | 
									/>
 | 
				
			||||||
 | 
									<meta
 | 
				
			||||||
 | 
										property="og:description"
 | 
				
			||||||
 | 
										content="Надаємо різноманітні сервіси-платформи, які дають змогу окремим особам і спільнотам спілкуватися, ділитися та розвиватися разом."
 | 
				
			||||||
 | 
									/>
 | 
				
			||||||
 | 
									<meta property="og:url" content="https://dead.guru/" />
 | 
				
			||||||
 | 
									<meta name="twitter:card" content="summary_large_image" />
 | 
				
			||||||
 | 
								</Head>
 | 
				
			||||||
 | 
								<header style={{ textAlign: "center" }} className="hero hero--primary">
 | 
				
			||||||
 | 
									<div className="container">
 | 
				
			||||||
 | 
										<h1 className="hero__title">
 | 
				
			||||||
 | 
											<img
 | 
				
			||||||
 | 
												style={{ paddingTop: "2rem", paddingBottom: "2rem" }}
 | 
				
			||||||
 | 
												alt="Dead Logo"
 | 
				
			||||||
 | 
												className="header__logo"
 | 
				
			||||||
 | 
												src={useBaseUrl("img/dead-banner.png")}
 | 
				
			||||||
 | 
											/>
 | 
				
			||||||
 | 
										</h1>
 | 
				
			||||||
 | 
										<p className="hero__subtitle">{siteConfig.tagline}</p>
 | 
				
			||||||
 | 
										<div className="indexCtas">
 | 
				
			||||||
 | 
											<Link className="button button--lg" to="/docs/introduction">
 | 
				
			||||||
 | 
												Дізнатися більше
 | 
				
			||||||
 | 
											</Link>
 | 
				
			||||||
 | 
											<Link className="button button--lg" to="/docs/getting-started">
 | 
				
			||||||
 | 
												Розпочати
 | 
				
			||||||
 | 
											</Link>
 | 
				
			||||||
 | 
										</div>
 | 
				
			||||||
 | 
									</div>
 | 
				
			||||||
 | 
								</header>
 | 
				
			||||||
 | 
								<main className="flex flex-col gap-4">
 | 
				
			||||||
 | 
									<Carousel autoPlay infiniteLoop showStatus={false} showThumbs={false}>
 | 
				
			||||||
 | 
										{features.map((feature) => (
 | 
				
			||||||
 | 
											<div key={feature.title} className="flex p-12">
 | 
				
			||||||
 | 
												<div className="w-1/2">
 | 
				
			||||||
 | 
													<img
 | 
				
			||||||
 | 
														className="my-auto h-40"
 | 
				
			||||||
 | 
														src={feature.imageUrl}
 | 
				
			||||||
 | 
														alt={feature.title}
 | 
				
			||||||
 | 
													/>
 | 
				
			||||||
 | 
												</div>
 | 
				
			||||||
 | 
												<div className="my-auto w-1/2">
 | 
				
			||||||
 | 
													<h3 className="text-xl font-medium">{feature.title}</h3>
 | 
				
			||||||
 | 
													<p>{feature.description}</p>
 | 
				
			||||||
 | 
												</div>
 | 
				
			||||||
 | 
											</div>
 | 
				
			||||||
 | 
										))}
 | 
				
			||||||
 | 
									</Carousel>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									<div className="bg-primaryDark mx-auto flex w-full lg:w-auto flex-col gap-4 p-4 shadow-inner">
 | 
				
			||||||
 | 
										<h3 className="text-xl font-bold">Приєднуйтесь до нас.</h3>
 | 
				
			||||||
 | 
										<div className="flex w-full overflow-x-auto">
 | 
				
			||||||
 | 
											{SocialCards.map((card) => (
 | 
				
			||||||
 | 
												<SocialCard key={card.link} color={card.color} link={card.link}>
 | 
				
			||||||
 | 
													{card.children}
 | 
				
			||||||
 | 
												</SocialCard>
 | 
				
			||||||
 | 
											))}
 | 
				
			||||||
 | 
										</div>
 | 
				
			||||||
 | 
									</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									<div className="container mx-auto flex w-auto flex-col">
 | 
				
			||||||
 | 
										<h2 className="mb-2 text-xl font-medium">
 | 
				
			||||||
 | 
											Доєднайтеся до "Мертвої" мережі в 3 кроки.
 | 
				
			||||||
 | 
										</h2>
 | 
				
			||||||
 | 
										<ul
 | 
				
			||||||
 | 
											className="mx-auto"
 | 
				
			||||||
 | 
											style={{
 | 
				
			||||||
 | 
												position: "relative",
 | 
				
			||||||
 | 
												display: "grid",
 | 
				
			||||||
 | 
												gap: "1.5rem",
 | 
				
			||||||
 | 
												gridTemplateColumns: "repeat(auto-fill, minmax(280px, 1fr))",
 | 
				
			||||||
 | 
												paddingLeft: "0",
 | 
				
			||||||
 | 
											}}
 | 
				
			||||||
 | 
										>
 | 
				
			||||||
 | 
											<div className="card">
 | 
				
			||||||
 | 
												<div
 | 
				
			||||||
 | 
													className="card__header"
 | 
				
			||||||
 | 
													style={{ display: "flex", justifyContent: "space-between" }}
 | 
				
			||||||
 | 
												>
 | 
				
			||||||
 | 
													<h3>1. Оберіть платформу</h3>
 | 
				
			||||||
 | 
												</div>
 | 
				
			||||||
 | 
												<div
 | 
				
			||||||
 | 
													className="card__body"
 | 
				
			||||||
 | 
													style={{ display: "flex", justifyContent: "center" }}
 | 
				
			||||||
 | 
												>
 | 
				
			||||||
 | 
													<p>
 | 
				
			||||||
 | 
														Для старту почніть з вибору платформи:
 | 
				
			||||||
 | 
														<ul>
 | 
				
			||||||
 | 
															<li>IRC</li>
 | 
				
			||||||
 | 
															<li>XMPP</li>
 | 
				
			||||||
 | 
															<li>Matrix</li>
 | 
				
			||||||
 | 
															<li>
 | 
				
			||||||
 | 
																Або взагалі проігноруйте сервіси повідомлень і почніть з{" "}
 | 
				
			||||||
 | 
																<a href="">
 | 
				
			||||||
 | 
																	<strong>ігрових серверів</strong>
 | 
				
			||||||
 | 
																</a>
 | 
				
			||||||
 | 
																!
 | 
				
			||||||
 | 
															</li>
 | 
				
			||||||
 | 
														</ul>
 | 
				
			||||||
 | 
													</p>
 | 
				
			||||||
 | 
												</div>
 | 
				
			||||||
 | 
											</div>
 | 
				
			||||||
 | 
											<div className="card">
 | 
				
			||||||
 | 
												<div
 | 
				
			||||||
 | 
													className="card__header"
 | 
				
			||||||
 | 
													style={{ display: "flex", justifyContent: "space-between" }}
 | 
				
			||||||
 | 
												>
 | 
				
			||||||
 | 
													<h3>2. Завантажте і зареєструйтесь!</h3>
 | 
				
			||||||
 | 
												</div>
 | 
				
			||||||
 | 
												<div
 | 
				
			||||||
 | 
													className="card__body"
 | 
				
			||||||
 | 
													style={{ display: "flex", justifyContent: "center" }}
 | 
				
			||||||
 | 
												>
 | 
				
			||||||
 | 
													<p>
 | 
				
			||||||
 | 
														<a href="/downloads">
 | 
				
			||||||
 | 
															<strong>Завантажте</strong>
 | 
				
			||||||
 | 
														</a>{" "}
 | 
				
			||||||
 | 
														додаток для обраної платформи, перегляньте наш{" "}
 | 
				
			||||||
 | 
														<a href="">
 | 
				
			||||||
 | 
															<strong>мануал по налаштуванню</strong>
 | 
				
			||||||
 | 
														</a>{" "}
 | 
				
			||||||
 | 
														і зареєструйтесь в сервісі мережі.
 | 
				
			||||||
 | 
													</p>
 | 
				
			||||||
 | 
												</div>
 | 
				
			||||||
 | 
											</div>
 | 
				
			||||||
 | 
											<div className="card">
 | 
				
			||||||
 | 
												<div
 | 
				
			||||||
 | 
													className="card__header"
 | 
				
			||||||
 | 
													style={{ display: "flex", justifyContent: "space-between" }}
 | 
				
			||||||
 | 
												>
 | 
				
			||||||
 | 
													<h3>3. Приєднайтесь до чату</h3>
 | 
				
			||||||
 | 
												</div>
 | 
				
			||||||
 | 
												<div
 | 
				
			||||||
 | 
													className="card__body"
 | 
				
			||||||
 | 
													style={{ display: "flex", justifyContent: "center" }}
 | 
				
			||||||
 | 
												>
 | 
				
			||||||
 | 
													<p>
 | 
				
			||||||
 | 
														В залежності від ваших інтересів і обраної платформи, ви
 | 
				
			||||||
 | 
														можете приєднатися до:
 | 
				
			||||||
 | 
														<ul>
 | 
				
			||||||
 | 
															<li>Загальний чат</li>
 | 
				
			||||||
 | 
															<li>ADHD Lab</li>
 | 
				
			||||||
 | 
															<li>Ігрові чати</li>
 | 
				
			||||||
 | 
															<li>HAM загальний чат</li>
 | 
				
			||||||
 | 
														</ul>
 | 
				
			||||||
 | 
													</p>
 | 
				
			||||||
 | 
												</div>
 | 
				
			||||||
 | 
											</div>
 | 
				
			||||||
 | 
										</ul>
 | 
				
			||||||
 | 
									</div>
 | 
				
			||||||
 | 
									<br />
 | 
				
			||||||
 | 
								</main>
 | 
				
			||||||
 | 
							</Layout>
 | 
				
			||||||
 | 
						);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default Home;
 | 
				
			||||||
							
								
								
									
										110
									
								
								src/pages/showcase/_components/Card.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,110 @@
 | 
				
			|||||||
 | 
					import React from "react";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { Showcase } from "../../../utils/apiTypes";
 | 
				
			||||||
 | 
					import { mapUrl } from "../../../utils/map";
 | 
				
			||||||
 | 
					import { CardTags } from "./CardTags";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export interface CardProps {
 | 
				
			||||||
 | 
						network: Showcase;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const Card = React.memo(({ network }: CardProps) => (
 | 
				
			||||||
 | 
						<div className="card">
 | 
				
			||||||
 | 
							<div className="card__image">
 | 
				
			||||||
 | 
								<div style={{ height: "140px" }}>
 | 
				
			||||||
 | 
									<img src={mapUrl(network.nodes ?? [])} alt={network.title} />
 | 
				
			||||||
 | 
								</div>
 | 
				
			||||||
 | 
							</div>
 | 
				
			||||||
 | 
							<div className="card__body">
 | 
				
			||||||
 | 
								<h4>{network.title}</h4>
 | 
				
			||||||
 | 
								<small>{network.summary}</small>
 | 
				
			||||||
 | 
							</div>
 | 
				
			||||||
 | 
							<div className="card__footer">
 | 
				
			||||||
 | 
								<a
 | 
				
			||||||
 | 
									href={`?id=${network.id}`}
 | 
				
			||||||
 | 
									className="button button--primary button--block"
 | 
				
			||||||
 | 
									style={{ marginBottom: "0.5rem" }}
 | 
				
			||||||
 | 
								>
 | 
				
			||||||
 | 
									Read more
 | 
				
			||||||
 | 
								</a>
 | 
				
			||||||
 | 
								<CardTags tags={network.tags} />
 | 
				
			||||||
 | 
							</div>
 | 
				
			||||||
 | 
						</div>
 | 
				
			||||||
 | 
					));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const PlaceholderCard = (): JSX.Element => (
 | 
				
			||||||
 | 
						<div
 | 
				
			||||||
 | 
							className="card"
 | 
				
			||||||
 | 
							style={{
 | 
				
			||||||
 | 
								animation: "pulse 2s infinite",
 | 
				
			||||||
 | 
								transform: "scale(1)",
 | 
				
			||||||
 | 
							}}
 | 
				
			||||||
 | 
						>
 | 
				
			||||||
 | 
							<div className="card__image">
 | 
				
			||||||
 | 
								<div
 | 
				
			||||||
 | 
									style={{
 | 
				
			||||||
 | 
										height: "140px",
 | 
				
			||||||
 | 
									}}
 | 
				
			||||||
 | 
								/>
 | 
				
			||||||
 | 
							</div>
 | 
				
			||||||
 | 
							<div className="card__body">
 | 
				
			||||||
 | 
								<div
 | 
				
			||||||
 | 
									style={{
 | 
				
			||||||
 | 
										width: "30%",
 | 
				
			||||||
 | 
										height: "2rem",
 | 
				
			||||||
 | 
										borderRadius: "0.4rem",
 | 
				
			||||||
 | 
										backgroundColor: "gray",
 | 
				
			||||||
 | 
										marginBottom: "1rem",
 | 
				
			||||||
 | 
									}}
 | 
				
			||||||
 | 
								/>
 | 
				
			||||||
 | 
								<div
 | 
				
			||||||
 | 
									style={{
 | 
				
			||||||
 | 
										width: "100%",
 | 
				
			||||||
 | 
										height: "1rem",
 | 
				
			||||||
 | 
										borderRadius: "0.4rem",
 | 
				
			||||||
 | 
										backgroundColor: "gray",
 | 
				
			||||||
 | 
										marginBottom: "0.5rem",
 | 
				
			||||||
 | 
									}}
 | 
				
			||||||
 | 
								/>
 | 
				
			||||||
 | 
								<div
 | 
				
			||||||
 | 
									style={{
 | 
				
			||||||
 | 
										width: "100%",
 | 
				
			||||||
 | 
										height: "1rem",
 | 
				
			||||||
 | 
										borderRadius: "0.4rem",
 | 
				
			||||||
 | 
										backgroundColor: "gray",
 | 
				
			||||||
 | 
									}}
 | 
				
			||||||
 | 
								/>
 | 
				
			||||||
 | 
							</div>
 | 
				
			||||||
 | 
							<div className="card__footer">
 | 
				
			||||||
 | 
								<button
 | 
				
			||||||
 | 
									className="button disabled button--primary button--block"
 | 
				
			||||||
 | 
									style={{ marginBottom: "0.5rem" }}
 | 
				
			||||||
 | 
								>
 | 
				
			||||||
 | 
									 
 | 
				
			||||||
 | 
								</button>
 | 
				
			||||||
 | 
								<div
 | 
				
			||||||
 | 
									style={{
 | 
				
			||||||
 | 
										display: "flex",
 | 
				
			||||||
 | 
										gap: "0.5rem",
 | 
				
			||||||
 | 
									}}
 | 
				
			||||||
 | 
								>
 | 
				
			||||||
 | 
									<div
 | 
				
			||||||
 | 
										style={{
 | 
				
			||||||
 | 
											width: "4rem",
 | 
				
			||||||
 | 
											height: "1.5rem",
 | 
				
			||||||
 | 
											borderRadius: "0.4rem",
 | 
				
			||||||
 | 
											backgroundColor: "gray",
 | 
				
			||||||
 | 
										}}
 | 
				
			||||||
 | 
									/>
 | 
				
			||||||
 | 
									<div
 | 
				
			||||||
 | 
										style={{
 | 
				
			||||||
 | 
											width: "4rem",
 | 
				
			||||||
 | 
											height: "1.5rem",
 | 
				
			||||||
 | 
											borderRadius: "0.4rem",
 | 
				
			||||||
 | 
											backgroundColor: "gray",
 | 
				
			||||||
 | 
										}}
 | 
				
			||||||
 | 
									/>
 | 
				
			||||||
 | 
								</div>
 | 
				
			||||||
 | 
							</div>
 | 
				
			||||||
 | 
						</div>
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
							
								
								
									
										29
									
								
								src/pages/showcase/_components/CardTags.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,29 @@
 | 
				
			|||||||
 | 
					import React from "react";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { ShowcaseTag } from "../../../utils/apiTypes";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export interface CardTagsProps {
 | 
				
			||||||
 | 
						tags: ShowcaseTag[];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const CardTags = ({ tags }: CardTagsProps) => {
 | 
				
			||||||
 | 
						return (
 | 
				
			||||||
 | 
							<div>
 | 
				
			||||||
 | 
								{tags.map(({ color, label }) => {
 | 
				
			||||||
 | 
									return (
 | 
				
			||||||
 | 
										<span
 | 
				
			||||||
 | 
											className="badge"
 | 
				
			||||||
 | 
											key={label}
 | 
				
			||||||
 | 
											style={{
 | 
				
			||||||
 | 
												backgroundColor: color,
 | 
				
			||||||
 | 
												marginRight: "0.3rem",
 | 
				
			||||||
 | 
												userSelect: "none",
 | 
				
			||||||
 | 
											}}
 | 
				
			||||||
 | 
										>
 | 
				
			||||||
 | 
											{label}
 | 
				
			||||||
 | 
										</span>
 | 
				
			||||||
 | 
									);
 | 
				
			||||||
 | 
								})}
 | 
				
			||||||
 | 
							</div>
 | 
				
			||||||
 | 
						);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
							
								
								
									
										90
									
								
								src/pages/showcase/_components/Filters.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,90 @@
 | 
				
			|||||||
 | 
					import React from "react";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { FiHeart } from "react-icons/fi";
 | 
				
			||||||
 | 
					import useSWR from "swr";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import useDocusaurusContext from "@docusaurus/useDocusaurusContext";
 | 
				
			||||||
 | 
					import { fetcher } from "../../../utils/swr";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { ShowcaseTag } from "../../../utils/apiTypes";
 | 
				
			||||||
 | 
					// import { TagList, Tags } from '../../../utils/showcase';
 | 
				
			||||||
 | 
					import { PlaceholderTagSelect, TagSelect } from "./TagSelect";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const Filters = (): JSX.Element => {
 | 
				
			||||||
 | 
						const { siteConfig } = useDocusaurusContext();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const { data, error } = useSWR<ShowcaseTag[]>(
 | 
				
			||||||
 | 
							`${siteConfig.customFields.API_URL}/showcase/tags`,
 | 
				
			||||||
 | 
							fetcher,
 | 
				
			||||||
 | 
						);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return (
 | 
				
			||||||
 | 
							<section className="margin-top--l margin-bottom--lg container">
 | 
				
			||||||
 | 
								{data && !error ? (
 | 
				
			||||||
 | 
									<ul
 | 
				
			||||||
 | 
										style={{
 | 
				
			||||||
 | 
											padding: "0",
 | 
				
			||||||
 | 
											display: "flex",
 | 
				
			||||||
 | 
											alignItems: "center",
 | 
				
			||||||
 | 
											flexWrap: "wrap",
 | 
				
			||||||
 | 
										}}
 | 
				
			||||||
 | 
									>
 | 
				
			||||||
 | 
										{data.map((tag) => {
 | 
				
			||||||
 | 
											const { label, color } = tag;
 | 
				
			||||||
 | 
											const id = `showcase_checkbox_id_${tag};`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
											return (
 | 
				
			||||||
 | 
												<div
 | 
				
			||||||
 | 
													key={tag.id}
 | 
				
			||||||
 | 
													style={{
 | 
				
			||||||
 | 
														boxSizing: "border-box",
 | 
				
			||||||
 | 
														position: "relative",
 | 
				
			||||||
 | 
														display: "inline-flex",
 | 
				
			||||||
 | 
														alignItems: "center",
 | 
				
			||||||
 | 
														height: "2rem",
 | 
				
			||||||
 | 
														marginTop: "0.5rem",
 | 
				
			||||||
 | 
														marginRight: "0.5rem",
 | 
				
			||||||
 | 
														fontSize: "0.875rem",
 | 
				
			||||||
 | 
														lineHeight: "1.25rem",
 | 
				
			||||||
 | 
														verticalAlign: "middle",
 | 
				
			||||||
 | 
														userSelect: "none",
 | 
				
			||||||
 | 
													}}
 | 
				
			||||||
 | 
												>
 | 
				
			||||||
 | 
													<TagSelect
 | 
				
			||||||
 | 
														tag={tag}
 | 
				
			||||||
 | 
														id={id}
 | 
				
			||||||
 | 
														label={label}
 | 
				
			||||||
 | 
														icon={
 | 
				
			||||||
 | 
															tag.label === "Favorite" ? (
 | 
				
			||||||
 | 
																<span
 | 
				
			||||||
 | 
																	style={{
 | 
				
			||||||
 | 
																		display: "flex",
 | 
				
			||||||
 | 
																		marginLeft: "0.5rem",
 | 
				
			||||||
 | 
																		color: "rgb(190 24 93)",
 | 
				
			||||||
 | 
																	}}
 | 
				
			||||||
 | 
																>
 | 
				
			||||||
 | 
																	<FiHeart />
 | 
				
			||||||
 | 
																</span>
 | 
				
			||||||
 | 
															) : (
 | 
				
			||||||
 | 
																<span
 | 
				
			||||||
 | 
																	style={{
 | 
				
			||||||
 | 
																		backgroundColor: color,
 | 
				
			||||||
 | 
																		width: 10,
 | 
				
			||||||
 | 
																		height: 10,
 | 
				
			||||||
 | 
																		borderRadius: "50%",
 | 
				
			||||||
 | 
																		marginLeft: 8,
 | 
				
			||||||
 | 
																	}}
 | 
				
			||||||
 | 
																/>
 | 
				
			||||||
 | 
															)
 | 
				
			||||||
 | 
														}
 | 
				
			||||||
 | 
													/>
 | 
				
			||||||
 | 
												</div>
 | 
				
			||||||
 | 
											);
 | 
				
			||||||
 | 
										})}
 | 
				
			||||||
 | 
									</ul>
 | 
				
			||||||
 | 
								) : (
 | 
				
			||||||
 | 
									<PlaceholderTagSelect />
 | 
				
			||||||
 | 
								)}
 | 
				
			||||||
 | 
							</section>
 | 
				
			||||||
 | 
						);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
							
								
								
									
										318
									
								
								src/pages/showcase/_components/Network.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,318 @@
 | 
				
			|||||||
 | 
					import React from "react";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import useSWR from "swr";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import useDocusaurusContext from "@docusaurus/useDocusaurusContext";
 | 
				
			||||||
 | 
					import { Showcase } from "../../../utils/apiTypes";
 | 
				
			||||||
 | 
					import { fetcher } from "../../../utils/swr";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					interface NetworkProps {
 | 
				
			||||||
 | 
						id: string;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const Network = ({ id }: NetworkProps): JSX.Element => {
 | 
				
			||||||
 | 
						const { siteConfig } = useDocusaurusContext();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const { data, error } = useSWR<Showcase>(
 | 
				
			||||||
 | 
							`${siteConfig.customFields.API_URL}/showcase/${id}`,
 | 
				
			||||||
 | 
							fetcher,
 | 
				
			||||||
 | 
						);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const githubData = useSWR(
 | 
				
			||||||
 | 
							`https://api.github.com/users/${data?.author?.githubUsername}`,
 | 
				
			||||||
 | 
							fetcher,
 | 
				
			||||||
 | 
						).data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return (
 | 
				
			||||||
 | 
							<div>
 | 
				
			||||||
 | 
								{data && !error ? (
 | 
				
			||||||
 | 
									<div className="container">
 | 
				
			||||||
 | 
										<h1>{data.title}</h1>
 | 
				
			||||||
 | 
										<p>{data.summary}</p>
 | 
				
			||||||
 | 
										{githubData && (
 | 
				
			||||||
 | 
											<div className="avatar">
 | 
				
			||||||
 | 
												<img
 | 
				
			||||||
 | 
													src={githubData.avatar_url}
 | 
				
			||||||
 | 
													alt={githubData.name}
 | 
				
			||||||
 | 
													className="avatar__photo"
 | 
				
			||||||
 | 
												/>
 | 
				
			||||||
 | 
												<div className="avatar__intro">
 | 
				
			||||||
 | 
													<div className="avatar__name">{githubData.name}</div>
 | 
				
			||||||
 | 
													<div className="avatar__subtitle">{githubData.bio}</div>
 | 
				
			||||||
 | 
												</div>
 | 
				
			||||||
 | 
											</div>
 | 
				
			||||||
 | 
										)}
 | 
				
			||||||
 | 
										<div className="markdown">{data.body}</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										<div
 | 
				
			||||||
 | 
											className="card"
 | 
				
			||||||
 | 
											style={{
 | 
				
			||||||
 | 
												marginLeft: "auto",
 | 
				
			||||||
 | 
												marginRight: "auto",
 | 
				
			||||||
 | 
												maxWidth: "900px",
 | 
				
			||||||
 | 
											}}
 | 
				
			||||||
 | 
										>
 | 
				
			||||||
 | 
											<div
 | 
				
			||||||
 | 
												className="card__header"
 | 
				
			||||||
 | 
												style={{
 | 
				
			||||||
 | 
													margin: "8px",
 | 
				
			||||||
 | 
												}}
 | 
				
			||||||
 | 
											>
 | 
				
			||||||
 | 
												<h2>Bill of Materials</h2>
 | 
				
			||||||
 | 
											</div>
 | 
				
			||||||
 | 
											<div className="card__body">
 | 
				
			||||||
 | 
												{data.materials?.map((material) => (
 | 
				
			||||||
 | 
													<div
 | 
				
			||||||
 | 
														key={material.id}
 | 
				
			||||||
 | 
														style={{
 | 
				
			||||||
 | 
															borderTop: "2px solid gray",
 | 
				
			||||||
 | 
															display: "flex",
 | 
				
			||||||
 | 
														}}
 | 
				
			||||||
 | 
													>
 | 
				
			||||||
 | 
														<div
 | 
				
			||||||
 | 
															style={{
 | 
				
			||||||
 | 
																width: "4rem",
 | 
				
			||||||
 | 
																display: "flex",
 | 
				
			||||||
 | 
															}}
 | 
				
			||||||
 | 
														>
 | 
				
			||||||
 | 
															<img
 | 
				
			||||||
 | 
																src={material.image}
 | 
				
			||||||
 | 
																height="auto"
 | 
				
			||||||
 | 
																width="100%"
 | 
				
			||||||
 | 
																style={{
 | 
				
			||||||
 | 
																	margin: "auto",
 | 
				
			||||||
 | 
																	padding: "4px",
 | 
				
			||||||
 | 
																	display: "block",
 | 
				
			||||||
 | 
																	maxWidth: "60px",
 | 
				
			||||||
 | 
																	maxHeight: "60px",
 | 
				
			||||||
 | 
																	width: "auto",
 | 
				
			||||||
 | 
																	height: "auto",
 | 
				
			||||||
 | 
																}}
 | 
				
			||||||
 | 
															/>
 | 
				
			||||||
 | 
														</div>
 | 
				
			||||||
 | 
														<div className="avatar__intro">
 | 
				
			||||||
 | 
															<div className="avatar__name">{material.name}</div>
 | 
				
			||||||
 | 
															<small className="avatar__subtitle">
 | 
				
			||||||
 | 
																{material.details}
 | 
				
			||||||
 | 
															</small>
 | 
				
			||||||
 | 
														</div>
 | 
				
			||||||
 | 
														<a
 | 
				
			||||||
 | 
															target="_blank"
 | 
				
			||||||
 | 
															rel="noreferrer"
 | 
				
			||||||
 | 
															href={material.url}
 | 
				
			||||||
 | 
															className="button button--outline button--secondary"
 | 
				
			||||||
 | 
															style={{
 | 
				
			||||||
 | 
																marginTop: "auto",
 | 
				
			||||||
 | 
																marginBottom: "auto",
 | 
				
			||||||
 | 
															}}
 | 
				
			||||||
 | 
														>
 | 
				
			||||||
 | 
															View
 | 
				
			||||||
 | 
														</a>
 | 
				
			||||||
 | 
													</div>
 | 
				
			||||||
 | 
												))}
 | 
				
			||||||
 | 
											</div>
 | 
				
			||||||
 | 
										</div>
 | 
				
			||||||
 | 
									</div>
 | 
				
			||||||
 | 
								) : (
 | 
				
			||||||
 | 
									<div>
 | 
				
			||||||
 | 
										{error && <div>{JSON.stringify(error)}</div>}
 | 
				
			||||||
 | 
										{!data && <PlaceholderNetwork />}
 | 
				
			||||||
 | 
									</div>
 | 
				
			||||||
 | 
								)}
 | 
				
			||||||
 | 
							</div>
 | 
				
			||||||
 | 
						);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const PlaceholderNetwork = (): JSX.Element => {
 | 
				
			||||||
 | 
						return (
 | 
				
			||||||
 | 
							<div
 | 
				
			||||||
 | 
								className="container"
 | 
				
			||||||
 | 
								style={{
 | 
				
			||||||
 | 
									display: "flex",
 | 
				
			||||||
 | 
									flexDirection: window.innerWidth > 768 ? "row" : "column",
 | 
				
			||||||
 | 
									gap: "2rem",
 | 
				
			||||||
 | 
								}}
 | 
				
			||||||
 | 
							>
 | 
				
			||||||
 | 
								<div
 | 
				
			||||||
 | 
									style={{
 | 
				
			||||||
 | 
										width: window.innerWidth > 768 ? "60%" : "100%",
 | 
				
			||||||
 | 
									}}
 | 
				
			||||||
 | 
								>
 | 
				
			||||||
 | 
									<div
 | 
				
			||||||
 | 
										className="card"
 | 
				
			||||||
 | 
										style={{
 | 
				
			||||||
 | 
											width: "100%",
 | 
				
			||||||
 | 
											animation: "pulse 2s infinite",
 | 
				
			||||||
 | 
											transform: "scale(1)",
 | 
				
			||||||
 | 
											display: "flex",
 | 
				
			||||||
 | 
											flexDirection: "column",
 | 
				
			||||||
 | 
											gap: "2rem",
 | 
				
			||||||
 | 
											padding: "2rem",
 | 
				
			||||||
 | 
										}}
 | 
				
			||||||
 | 
									>
 | 
				
			||||||
 | 
										<div
 | 
				
			||||||
 | 
											style={{
 | 
				
			||||||
 | 
												borderRadius: "0.4rem",
 | 
				
			||||||
 | 
												backgroundColor: "gray",
 | 
				
			||||||
 | 
												height: "4rem",
 | 
				
			||||||
 | 
											}}
 | 
				
			||||||
 | 
										/>
 | 
				
			||||||
 | 
										<div
 | 
				
			||||||
 | 
											style={{
 | 
				
			||||||
 | 
												borderRadius: "0.4rem",
 | 
				
			||||||
 | 
												backgroundColor: "gray",
 | 
				
			||||||
 | 
												height: "12rem",
 | 
				
			||||||
 | 
											}}
 | 
				
			||||||
 | 
										/>
 | 
				
			||||||
 | 
										<div style={{ display: "flex", gap: "1rem" }}>
 | 
				
			||||||
 | 
											<div
 | 
				
			||||||
 | 
												style={{
 | 
				
			||||||
 | 
													borderRadius: "999px",
 | 
				
			||||||
 | 
													backgroundColor: "gray",
 | 
				
			||||||
 | 
													height: "4rem",
 | 
				
			||||||
 | 
													width: "4rem",
 | 
				
			||||||
 | 
													minWidth: "4rem",
 | 
				
			||||||
 | 
												}}
 | 
				
			||||||
 | 
											/>
 | 
				
			||||||
 | 
											<div
 | 
				
			||||||
 | 
												style={{
 | 
				
			||||||
 | 
													display: "flex",
 | 
				
			||||||
 | 
													flexDirection: "column",
 | 
				
			||||||
 | 
													gap: "1rem",
 | 
				
			||||||
 | 
													width: "100%",
 | 
				
			||||||
 | 
												}}
 | 
				
			||||||
 | 
											>
 | 
				
			||||||
 | 
												<div
 | 
				
			||||||
 | 
													style={{
 | 
				
			||||||
 | 
														width: "100%",
 | 
				
			||||||
 | 
														borderRadius: "0.4rem",
 | 
				
			||||||
 | 
														backgroundColor: "gray",
 | 
				
			||||||
 | 
														height: "1rem",
 | 
				
			||||||
 | 
													}}
 | 
				
			||||||
 | 
												/>
 | 
				
			||||||
 | 
												<div
 | 
				
			||||||
 | 
													style={{
 | 
				
			||||||
 | 
														width: "100%",
 | 
				
			||||||
 | 
														borderRadius: "0.4rem",
 | 
				
			||||||
 | 
														backgroundColor: "gray",
 | 
				
			||||||
 | 
														height: "2rem",
 | 
				
			||||||
 | 
													}}
 | 
				
			||||||
 | 
												/>
 | 
				
			||||||
 | 
											</div>
 | 
				
			||||||
 | 
										</div>
 | 
				
			||||||
 | 
									</div>
 | 
				
			||||||
 | 
								</div>
 | 
				
			||||||
 | 
								<div
 | 
				
			||||||
 | 
									style={{
 | 
				
			||||||
 | 
										width: window.innerWidth > 768 ? "40%" : "100%",
 | 
				
			||||||
 | 
									}}
 | 
				
			||||||
 | 
								>
 | 
				
			||||||
 | 
									<div
 | 
				
			||||||
 | 
										className="card"
 | 
				
			||||||
 | 
										style={{
 | 
				
			||||||
 | 
											width: "100%",
 | 
				
			||||||
 | 
											animation: "pulse 2s infinite",
 | 
				
			||||||
 | 
											transform: "scale(1)",
 | 
				
			||||||
 | 
											display: "flex",
 | 
				
			||||||
 | 
											flexDirection: "column",
 | 
				
			||||||
 | 
											gap: "2rem",
 | 
				
			||||||
 | 
											padding: "2rem",
 | 
				
			||||||
 | 
										}}
 | 
				
			||||||
 | 
									>
 | 
				
			||||||
 | 
										<div
 | 
				
			||||||
 | 
											style={{
 | 
				
			||||||
 | 
												borderRadius: "0.4rem",
 | 
				
			||||||
 | 
												backgroundColor: "gray",
 | 
				
			||||||
 | 
												height: "12rem",
 | 
				
			||||||
 | 
											}}
 | 
				
			||||||
 | 
										/>
 | 
				
			||||||
 | 
										<div
 | 
				
			||||||
 | 
											style={{
 | 
				
			||||||
 | 
												borderRadius: "0.4rem",
 | 
				
			||||||
 | 
												backgroundColor: "gray",
 | 
				
			||||||
 | 
												height: "2rem",
 | 
				
			||||||
 | 
											}}
 | 
				
			||||||
 | 
										/>
 | 
				
			||||||
 | 
										<div style={{ display: "flex", gap: "0.5rem" }}>
 | 
				
			||||||
 | 
											<div
 | 
				
			||||||
 | 
												style={{
 | 
				
			||||||
 | 
													width: "7rem",
 | 
				
			||||||
 | 
													height: "1.8rem",
 | 
				
			||||||
 | 
													borderRadius: "0.4rem",
 | 
				
			||||||
 | 
													backgroundColor: "gray",
 | 
				
			||||||
 | 
												}}
 | 
				
			||||||
 | 
											/>
 | 
				
			||||||
 | 
											<div
 | 
				
			||||||
 | 
												style={{
 | 
				
			||||||
 | 
													width: "7rem",
 | 
				
			||||||
 | 
													height: "1.8rem",
 | 
				
			||||||
 | 
													borderRadius: "0.4rem",
 | 
				
			||||||
 | 
													backgroundColor: "gray",
 | 
				
			||||||
 | 
												}}
 | 
				
			||||||
 | 
											/>
 | 
				
			||||||
 | 
											<div
 | 
				
			||||||
 | 
												style={{
 | 
				
			||||||
 | 
													width: "7rem",
 | 
				
			||||||
 | 
													height: "1.8rem",
 | 
				
			||||||
 | 
													borderRadius: "0.4rem",
 | 
				
			||||||
 | 
													backgroundColor: "gray",
 | 
				
			||||||
 | 
												}}
 | 
				
			||||||
 | 
											/>
 | 
				
			||||||
 | 
										</div>
 | 
				
			||||||
 | 
										<div
 | 
				
			||||||
 | 
											style={{ display: "flex", flexDirection: "column", gap: "1rem" }}
 | 
				
			||||||
 | 
										>
 | 
				
			||||||
 | 
											<div style={{ display: "flex", gap: "1rem" }}>
 | 
				
			||||||
 | 
												<div
 | 
				
			||||||
 | 
													style={{
 | 
				
			||||||
 | 
														borderRadius: "0.4rem",
 | 
				
			||||||
 | 
														backgroundColor: "gray",
 | 
				
			||||||
 | 
														height: "2.5rem",
 | 
				
			||||||
 | 
														width: "20%",
 | 
				
			||||||
 | 
													}}
 | 
				
			||||||
 | 
												/>
 | 
				
			||||||
 | 
												<div
 | 
				
			||||||
 | 
													style={{
 | 
				
			||||||
 | 
														borderRadius: "0.4rem",
 | 
				
			||||||
 | 
														backgroundColor: "gray",
 | 
				
			||||||
 | 
														height: "2.5rem",
 | 
				
			||||||
 | 
														width: "60%",
 | 
				
			||||||
 | 
													}}
 | 
				
			||||||
 | 
												/>
 | 
				
			||||||
 | 
												<a
 | 
				
			||||||
 | 
													className="button disabled button--primary button--block"
 | 
				
			||||||
 | 
													style={{ width: "20%" }}
 | 
				
			||||||
 | 
												>
 | 
				
			||||||
 | 
													 
 | 
				
			||||||
 | 
												</a>
 | 
				
			||||||
 | 
											</div>
 | 
				
			||||||
 | 
											<div style={{ display: "flex", gap: "1rem" }}>
 | 
				
			||||||
 | 
												<div
 | 
				
			||||||
 | 
													style={{
 | 
				
			||||||
 | 
														borderRadius: "0.4rem",
 | 
				
			||||||
 | 
														backgroundColor: "gray",
 | 
				
			||||||
 | 
														height: "2.5rem",
 | 
				
			||||||
 | 
														width: "20%",
 | 
				
			||||||
 | 
													}}
 | 
				
			||||||
 | 
												/>
 | 
				
			||||||
 | 
												<div
 | 
				
			||||||
 | 
													style={{
 | 
				
			||||||
 | 
														borderRadius: "0.4rem",
 | 
				
			||||||
 | 
														backgroundColor: "gray",
 | 
				
			||||||
 | 
														height: "2.5rem",
 | 
				
			||||||
 | 
														width: "60%",
 | 
				
			||||||
 | 
													}}
 | 
				
			||||||
 | 
												/>
 | 
				
			||||||
 | 
												<a
 | 
				
			||||||
 | 
													className="button disabled button--primary button--block"
 | 
				
			||||||
 | 
													style={{ width: "20%" }}
 | 
				
			||||||
 | 
												>
 | 
				
			||||||
 | 
													 
 | 
				
			||||||
 | 
												</a>
 | 
				
			||||||
 | 
											</div>
 | 
				
			||||||
 | 
										</div>
 | 
				
			||||||
 | 
									</div>
 | 
				
			||||||
 | 
								</div>
 | 
				
			||||||
 | 
							</div>
 | 
				
			||||||
 | 
						);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
							
								
								
									
										67
									
								
								src/pages/showcase/_components/NetworkSection.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,67 @@
 | 
				
			|||||||
 | 
					import React from "react";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { Showcase } from "../../../utils/apiTypes";
 | 
				
			||||||
 | 
					import { Card, PlaceholderCard } from "./Card";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					interface NetworkSectionProps {
 | 
				
			||||||
 | 
						title: string;
 | 
				
			||||||
 | 
						icon?: JSX.Element;
 | 
				
			||||||
 | 
						iconColor?: string;
 | 
				
			||||||
 | 
						networks?: Showcase[];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const NetworkSection = ({
 | 
				
			||||||
 | 
						title,
 | 
				
			||||||
 | 
						icon,
 | 
				
			||||||
 | 
						iconColor,
 | 
				
			||||||
 | 
						networks,
 | 
				
			||||||
 | 
					}: NetworkSectionProps): JSX.Element => {
 | 
				
			||||||
 | 
						return (
 | 
				
			||||||
 | 
							<div className="margin-top--lg container">
 | 
				
			||||||
 | 
								<div
 | 
				
			||||||
 | 
									className="margin-bottom--sm"
 | 
				
			||||||
 | 
									style={{
 | 
				
			||||||
 | 
										display: "flex",
 | 
				
			||||||
 | 
										alignItems: "center",
 | 
				
			||||||
 | 
									}}
 | 
				
			||||||
 | 
								>
 | 
				
			||||||
 | 
									<h2>{title}</h2>
 | 
				
			||||||
 | 
									{icon && (
 | 
				
			||||||
 | 
										<span
 | 
				
			||||||
 | 
											style={{
 | 
				
			||||||
 | 
												marginBottom: "0.5rem",
 | 
				
			||||||
 | 
												marginLeft: "0.5rem",
 | 
				
			||||||
 | 
												fontSize: "1.25rem",
 | 
				
			||||||
 | 
												lineHeight: "1.75rem",
 | 
				
			||||||
 | 
												color: iconColor,
 | 
				
			||||||
 | 
											}}
 | 
				
			||||||
 | 
										>
 | 
				
			||||||
 | 
											{icon}
 | 
				
			||||||
 | 
										</span>
 | 
				
			||||||
 | 
									)}
 | 
				
			||||||
 | 
								</div>
 | 
				
			||||||
 | 
								<ul
 | 
				
			||||||
 | 
									style={{
 | 
				
			||||||
 | 
										position: "relative",
 | 
				
			||||||
 | 
										display: "grid",
 | 
				
			||||||
 | 
										gap: "1.5rem",
 | 
				
			||||||
 | 
										gridTemplateColumns: "repeat(auto-fill, minmax(280px, 1fr))",
 | 
				
			||||||
 | 
										paddingLeft: "0",
 | 
				
			||||||
 | 
									}}
 | 
				
			||||||
 | 
								>
 | 
				
			||||||
 | 
									{networks ? (
 | 
				
			||||||
 | 
										<>
 | 
				
			||||||
 | 
											{networks.map((network) => (
 | 
				
			||||||
 | 
												<Card key={network.title} network={network} />
 | 
				
			||||||
 | 
											))}
 | 
				
			||||||
 | 
											{networks.length === 0 && <h2>No result</h2>}
 | 
				
			||||||
 | 
										</>
 | 
				
			||||||
 | 
									) : (
 | 
				
			||||||
 | 
										<div>
 | 
				
			||||||
 | 
											<PlaceholderCard />
 | 
				
			||||||
 | 
										</div>
 | 
				
			||||||
 | 
									)}
 | 
				
			||||||
 | 
								</ul>
 | 
				
			||||||
 | 
							</div>
 | 
				
			||||||
 | 
						);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
							
								
								
									
										52
									
								
								src/pages/showcase/_components/Networks.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,52 @@
 | 
				
			|||||||
 | 
					import React from "react";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { FiHeart, FiSearch } from "react-icons/fi";
 | 
				
			||||||
 | 
					import useSWR from "swr";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import useDocusaurusContext from "@docusaurus/useDocusaurusContext";
 | 
				
			||||||
 | 
					import { useSelectedTags } from "../../../hooks/useSelectedTags";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { useFilteredNetworks } from "../../../hooks/useFilteredNetworks";
 | 
				
			||||||
 | 
					import { Showcase } from "../../../utils/apiTypes";
 | 
				
			||||||
 | 
					import { fetcher } from "../../../utils/swr";
 | 
				
			||||||
 | 
					import { NetworkSection } from "./NetworkSection";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const Networks = (): JSX.Element => {
 | 
				
			||||||
 | 
						const { siteConfig } = useDocusaurusContext();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const { data, error } = useSWR<Showcase[]>(
 | 
				
			||||||
 | 
							`${siteConfig.customFields.API_URL}/showcase`,
 | 
				
			||||||
 | 
							fetcher,
 | 
				
			||||||
 | 
						);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const selectedTags = useSelectedTags();
 | 
				
			||||||
 | 
						const filteredNetworks = useFilteredNetworks(data ?? []);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return (
 | 
				
			||||||
 | 
							<section className="margin-top--lg margin-bottom--xl">
 | 
				
			||||||
 | 
								{!error ? (
 | 
				
			||||||
 | 
									selectedTags.length === 0 ? (
 | 
				
			||||||
 | 
										<>
 | 
				
			||||||
 | 
											<NetworkSection
 | 
				
			||||||
 | 
												title="Our favorites"
 | 
				
			||||||
 | 
												icon={<FiHeart />}
 | 
				
			||||||
 | 
												iconColor="rgb(190 24 93)"
 | 
				
			||||||
 | 
												networks={data?.filter((network) =>
 | 
				
			||||||
 | 
													network.tags.find((tag) => tag.label === "Favorite"),
 | 
				
			||||||
 | 
												)}
 | 
				
			||||||
 | 
											/>
 | 
				
			||||||
 | 
											<NetworkSection title="All networks" networks={data} />
 | 
				
			||||||
 | 
										</>
 | 
				
			||||||
 | 
									) : (
 | 
				
			||||||
 | 
										<NetworkSection
 | 
				
			||||||
 | 
											title="Results"
 | 
				
			||||||
 | 
											icon={<FiSearch />}
 | 
				
			||||||
 | 
											networks={filteredNetworks}
 | 
				
			||||||
 | 
										/>
 | 
				
			||||||
 | 
									)
 | 
				
			||||||
 | 
								) : (
 | 
				
			||||||
 | 
									<div>{JSON.stringify(error)}</div>
 | 
				
			||||||
 | 
								)}
 | 
				
			||||||
 | 
							</section>
 | 
				
			||||||
 | 
						);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
							
								
								
									
										111
									
								
								src/pages/showcase/_components/TagSelect.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,111 @@
 | 
				
			|||||||
 | 
					import "url-search-params-polyfill";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import React from "react";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { useHistory, useLocation } from "@docusaurus/router";
 | 
				
			||||||
 | 
					import { ShowcaseTag } from "../../../utils/apiTypes";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { toggleListItem } from "../../../utils/showcase";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					interface Props extends React.ComponentProps<"input"> {
 | 
				
			||||||
 | 
						icon: React.ReactElement<React.ComponentProps<"svg">>;
 | 
				
			||||||
 | 
						label: React.ReactNode;
 | 
				
			||||||
 | 
						tag: ShowcaseTag;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function readSearchTags(search: string): string[] {
 | 
				
			||||||
 | 
						return new URLSearchParams(search).getAll("tags");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function replaceSearchTags(search: string, newTags: string[]) {
 | 
				
			||||||
 | 
						const searchParams = new URLSearchParams(search);
 | 
				
			||||||
 | 
						searchParams.delete("tags");
 | 
				
			||||||
 | 
						newTags.forEach((tag) => searchParams.append("tags", tag));
 | 
				
			||||||
 | 
						return searchParams.toString();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const TagSelect = React.forwardRef<HTMLLabelElement, Props>(
 | 
				
			||||||
 | 
						({ icon, label, tag }) => {
 | 
				
			||||||
 | 
							const location = useLocation();
 | 
				
			||||||
 | 
							const history = useHistory();
 | 
				
			||||||
 | 
							const [selected, setSelected] = React.useState(false);
 | 
				
			||||||
 | 
							React.useEffect(() => {
 | 
				
			||||||
 | 
								const tags = readSearchTags(location.search);
 | 
				
			||||||
 | 
								setSelected(tags.includes(tag.label));
 | 
				
			||||||
 | 
							}, [tag, location]);
 | 
				
			||||||
 | 
							const toggleTag = React.useCallback(() => {
 | 
				
			||||||
 | 
								const tags = readSearchTags(location.search);
 | 
				
			||||||
 | 
								const newTags = toggleListItem(tags, tag.label);
 | 
				
			||||||
 | 
								const newSearch = replaceSearchTags(location.search, newTags);
 | 
				
			||||||
 | 
								history.push({ ...location, search: newSearch });
 | 
				
			||||||
 | 
							}, [tag, location, history]);
 | 
				
			||||||
 | 
							return (
 | 
				
			||||||
 | 
								<button
 | 
				
			||||||
 | 
									style={{
 | 
				
			||||||
 | 
										display: "flex",
 | 
				
			||||||
 | 
										alignItems: "center",
 | 
				
			||||||
 | 
									}}
 | 
				
			||||||
 | 
									className={`button button--sm button--outline button--secondary ${
 | 
				
			||||||
 | 
										selected ? "button--active" : ""
 | 
				
			||||||
 | 
									}`}
 | 
				
			||||||
 | 
									onClick={() => {
 | 
				
			||||||
 | 
										toggleTag();
 | 
				
			||||||
 | 
									}}
 | 
				
			||||||
 | 
								>
 | 
				
			||||||
 | 
									{label}
 | 
				
			||||||
 | 
									{icon}
 | 
				
			||||||
 | 
								</button>
 | 
				
			||||||
 | 
							);
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const PlaceholderTagSelect = (): JSX.Element => (
 | 
				
			||||||
 | 
						<div
 | 
				
			||||||
 | 
							style={{
 | 
				
			||||||
 | 
								boxSizing: "border-box",
 | 
				
			||||||
 | 
								position: "relative",
 | 
				
			||||||
 | 
								display: "inline-flex",
 | 
				
			||||||
 | 
								alignItems: "center",
 | 
				
			||||||
 | 
								height: "2rem",
 | 
				
			||||||
 | 
								marginTop: "0.5rem",
 | 
				
			||||||
 | 
								marginRight: "0.5rem",
 | 
				
			||||||
 | 
								fontSize: "0.875rem",
 | 
				
			||||||
 | 
								lineHeight: "1.25rem",
 | 
				
			||||||
 | 
								verticalAlign: "middle",
 | 
				
			||||||
 | 
								userSelect: "none",
 | 
				
			||||||
 | 
							}}
 | 
				
			||||||
 | 
						>
 | 
				
			||||||
 | 
							<div
 | 
				
			||||||
 | 
								style={{
 | 
				
			||||||
 | 
									width: "7rem",
 | 
				
			||||||
 | 
									height: "1.8rem",
 | 
				
			||||||
 | 
									borderRadius: "0.4rem",
 | 
				
			||||||
 | 
									backgroundColor: "gray",
 | 
				
			||||||
 | 
									animation: "pulse 2s infinite",
 | 
				
			||||||
 | 
									transform: "scale(1)",
 | 
				
			||||||
 | 
								}}
 | 
				
			||||||
 | 
							/>
 | 
				
			||||||
 | 
							<div
 | 
				
			||||||
 | 
								style={{
 | 
				
			||||||
 | 
									width: "7rem",
 | 
				
			||||||
 | 
									height: "1.8rem",
 | 
				
			||||||
 | 
									borderRadius: "0.4rem",
 | 
				
			||||||
 | 
									backgroundColor: "gray",
 | 
				
			||||||
 | 
									animation: "pulse 2s infinite",
 | 
				
			||||||
 | 
									transform: "scale(1)",
 | 
				
			||||||
 | 
									marginLeft: 8,
 | 
				
			||||||
 | 
								}}
 | 
				
			||||||
 | 
							/>
 | 
				
			||||||
 | 
							<div
 | 
				
			||||||
 | 
								style={{
 | 
				
			||||||
 | 
									width: "7rem",
 | 
				
			||||||
 | 
									height: "1.8rem",
 | 
				
			||||||
 | 
									borderRadius: "0.4rem",
 | 
				
			||||||
 | 
									backgroundColor: "gray",
 | 
				
			||||||
 | 
									animation: "pulse 2s infinite",
 | 
				
			||||||
 | 
									transform: "scale(1)",
 | 
				
			||||||
 | 
									marginLeft: 8,
 | 
				
			||||||
 | 
								}}
 | 
				
			||||||
 | 
							/>
 | 
				
			||||||
 | 
						</div>
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
							
								
								
									
										35
									
								
								src/pages/showcase/index.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,35 @@
 | 
				
			|||||||
 | 
					import "url-search-params-polyfill";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import React from "react";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { useLocation } from "@docusaurus/router";
 | 
				
			||||||
 | 
					import Layout from "@theme/Layout";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { Filters } from "./_components/Filters";
 | 
				
			||||||
 | 
					import { Network } from "./_components/Network";
 | 
				
			||||||
 | 
					import { Networks } from "./_components/Networks";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const Showcase = (): JSX.Element => {
 | 
				
			||||||
 | 
						const location = useLocation();
 | 
				
			||||||
 | 
						const id = new URLSearchParams(location.search).get("id");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return (
 | 
				
			||||||
 | 
							<Layout
 | 
				
			||||||
 | 
								title="Showcase"
 | 
				
			||||||
 | 
								description="Portfolio of projects from the Dead community"
 | 
				
			||||||
 | 
							>
 | 
				
			||||||
 | 
								<main className="margin-vert--lg">
 | 
				
			||||||
 | 
									{id ? (
 | 
				
			||||||
 | 
										<Network id={id} />
 | 
				
			||||||
 | 
									) : (
 | 
				
			||||||
 | 
										<>
 | 
				
			||||||
 | 
											<Filters />
 | 
				
			||||||
 | 
											<Networks />
 | 
				
			||||||
 | 
										</>
 | 
				
			||||||
 | 
									)}
 | 
				
			||||||
 | 
								</main>
 | 
				
			||||||
 | 
							</Layout>
 | 
				
			||||||
 | 
						);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default Showcase;
 | 
				
			||||||
							
								
								
									
										151
									
								
								src/pages/tools/OEM.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,151 @@
 | 
				
			|||||||
 | 
					import React, { useEffect, useState } from "react";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { fromByteArray, toByteArray } from "base64-js";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { Protobuf } from "@meshtastic/meshtasticjs";
 | 
				
			||||||
 | 
					import Layout from "@theme/Layout";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const OEM = (): JSX.Element => {
 | 
				
			||||||
 | 
						const [oemAesKey, setOemAesKey] = useState<Uint8Array>(new Uint8Array());
 | 
				
			||||||
 | 
						const [oemFont, setOemFont] = useState<Protobuf.ScreenFonts>(
 | 
				
			||||||
 | 
							Protobuf.ScreenFonts.FONT_MEDIUM,
 | 
				
			||||||
 | 
						);
 | 
				
			||||||
 | 
						const [oemIconBits, setOemIconBits] = useState<Uint8Array>(new Uint8Array());
 | 
				
			||||||
 | 
						const [oemIconHeight, setOemIconHeight] = useState<number>(0);
 | 
				
			||||||
 | 
						const [oemIconWidth, setOemIconWidth] = useState<number>(0);
 | 
				
			||||||
 | 
						const [oemText, setOemText] = useState<string>("");
 | 
				
			||||||
 | 
						const [oemBytes, setOemBytes] = useState<Uint8Array>(new Uint8Array());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						useEffect(() => {
 | 
				
			||||||
 | 
							setOemBytes(
 | 
				
			||||||
 | 
								Protobuf.OEMStore.toBinary({
 | 
				
			||||||
 | 
									oemAesKey,
 | 
				
			||||||
 | 
									oemFont,
 | 
				
			||||||
 | 
									oemIconBits,
 | 
				
			||||||
 | 
									oemIconHeight,
 | 
				
			||||||
 | 
									oemIconWidth,
 | 
				
			||||||
 | 
									oemText,
 | 
				
			||||||
 | 
								}),
 | 
				
			||||||
 | 
							);
 | 
				
			||||||
 | 
						}, [oemAesKey, oemFont, oemIconBits, oemIconHeight, oemIconWidth, oemText]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const enumOptions = Protobuf.ScreenFonts
 | 
				
			||||||
 | 
							? Object.entries(Protobuf.ScreenFonts).filter(
 | 
				
			||||||
 | 
									(value) => typeof value[1] === "number",
 | 
				
			||||||
 | 
							  )
 | 
				
			||||||
 | 
							: [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const readFile = (file: File) => {
 | 
				
			||||||
 | 
							return new Promise((resolve: (value: string) => void, reject) => {
 | 
				
			||||||
 | 
								const reader = new FileReader();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								reader.onload = (res) => {
 | 
				
			||||||
 | 
									resolve(res.target.result as string);
 | 
				
			||||||
 | 
								};
 | 
				
			||||||
 | 
								reader.onerror = (err) => reject(err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								reader.readAsText(file);
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return (
 | 
				
			||||||
 | 
							<Layout title="OEM Generator" description="OEM Bin Generator">
 | 
				
			||||||
 | 
								<div className="container mt-8 flex flex-col gap-3">
 | 
				
			||||||
 | 
									<span>AES Key</span>
 | 
				
			||||||
 | 
									<div className="flex gap-2">
 | 
				
			||||||
 | 
										<button
 | 
				
			||||||
 | 
											onClick={() => {
 | 
				
			||||||
 | 
												const key = new Uint8Array(128 / 8);
 | 
				
			||||||
 | 
												setOemAesKey(crypto.getRandomValues(key));
 | 
				
			||||||
 | 
											}}
 | 
				
			||||||
 | 
											className="cursor-pointer rounded-md bg-tertiary p-2 hover:brightness-90"
 | 
				
			||||||
 | 
										>
 | 
				
			||||||
 | 
											Generate 128bit
 | 
				
			||||||
 | 
										</button>
 | 
				
			||||||
 | 
										<button
 | 
				
			||||||
 | 
											onClick={() => {
 | 
				
			||||||
 | 
												const key = new Uint8Array(256 / 8);
 | 
				
			||||||
 | 
												setOemAesKey(crypto.getRandomValues(key));
 | 
				
			||||||
 | 
											}}
 | 
				
			||||||
 | 
											className="mr-auto cursor-pointer rounded-md bg-tertiary p-2 hover:brightness-90"
 | 
				
			||||||
 | 
										>
 | 
				
			||||||
 | 
											Generate 256bit
 | 
				
			||||||
 | 
										</button>
 | 
				
			||||||
 | 
									</div>
 | 
				
			||||||
 | 
									<input
 | 
				
			||||||
 | 
										type="text"
 | 
				
			||||||
 | 
										name="oemAesKey"
 | 
				
			||||||
 | 
										value={fromByteArray(oemAesKey)}
 | 
				
			||||||
 | 
										onChange={(e) => {
 | 
				
			||||||
 | 
											setOemAesKey(toByteArray(e.target.value));
 | 
				
			||||||
 | 
										}}
 | 
				
			||||||
 | 
									/>
 | 
				
			||||||
 | 
									<span>Font</span>
 | 
				
			||||||
 | 
									<select
 | 
				
			||||||
 | 
										onChange={(e) => {
 | 
				
			||||||
 | 
											setOemFont(parseInt(e.target.value));
 | 
				
			||||||
 | 
										}}
 | 
				
			||||||
 | 
									>
 | 
				
			||||||
 | 
										{enumOptions.map(([name, value]) => (
 | 
				
			||||||
 | 
											<option key={name} value={value}>
 | 
				
			||||||
 | 
												{name}
 | 
				
			||||||
 | 
											</option>
 | 
				
			||||||
 | 
										))}
 | 
				
			||||||
 | 
									</select>
 | 
				
			||||||
 | 
									<span>Logo XBM</span>
 | 
				
			||||||
 | 
									<input
 | 
				
			||||||
 | 
										type="file"
 | 
				
			||||||
 | 
										name="file"
 | 
				
			||||||
 | 
										onChange={(e) => {
 | 
				
			||||||
 | 
											readFile(e.target.files[0]).then((data) => {
 | 
				
			||||||
 | 
												setOemIconBits(
 | 
				
			||||||
 | 
													new Uint8Array(
 | 
				
			||||||
 | 
														data.split(",").map((s) => parseInt(s.trim(), 16)),
 | 
				
			||||||
 | 
													),
 | 
				
			||||||
 | 
												);
 | 
				
			||||||
 | 
											});
 | 
				
			||||||
 | 
										}}
 | 
				
			||||||
 | 
									/>
 | 
				
			||||||
 | 
									<span>Logo Height</span>
 | 
				
			||||||
 | 
									<input
 | 
				
			||||||
 | 
										type="number"
 | 
				
			||||||
 | 
										name="oemIconHeight"
 | 
				
			||||||
 | 
										onChange={(e) => {
 | 
				
			||||||
 | 
											setOemIconHeight(parseInt(e.target.value));
 | 
				
			||||||
 | 
										}}
 | 
				
			||||||
 | 
									/>
 | 
				
			||||||
 | 
									<span>Logo Width</span>
 | 
				
			||||||
 | 
									<input
 | 
				
			||||||
 | 
										type="number"
 | 
				
			||||||
 | 
										name="oemIconWidth"
 | 
				
			||||||
 | 
										onChange={(e) => {
 | 
				
			||||||
 | 
											setOemIconWidth(parseInt(e.target.value));
 | 
				
			||||||
 | 
										}}
 | 
				
			||||||
 | 
									/>
 | 
				
			||||||
 | 
									<span>Boot Text</span>
 | 
				
			||||||
 | 
									<input
 | 
				
			||||||
 | 
										type="text"
 | 
				
			||||||
 | 
										name="oemText"
 | 
				
			||||||
 | 
										onChange={(e) => {
 | 
				
			||||||
 | 
											setOemText(e.target.value);
 | 
				
			||||||
 | 
										}}
 | 
				
			||||||
 | 
									/>
 | 
				
			||||||
 | 
									<a
 | 
				
			||||||
 | 
										className="cursor-pointer rounded-md bg-tertiary p-2 hover:brightness-90"
 | 
				
			||||||
 | 
										download="OEM.bin"
 | 
				
			||||||
 | 
										onClick={() => {
 | 
				
			||||||
 | 
											const blob = new Blob([oemBytes], {
 | 
				
			||||||
 | 
												type: "application/octet-stream",
 | 
				
			||||||
 | 
											});
 | 
				
			||||||
 | 
											window.open(URL.createObjectURL(blob));
 | 
				
			||||||
 | 
										}}
 | 
				
			||||||
 | 
									>
 | 
				
			||||||
 | 
										Download
 | 
				
			||||||
 | 
									</a>
 | 
				
			||||||
 | 
									{oemBytes.toString()}
 | 
				
			||||||
 | 
								</div>
 | 
				
			||||||
 | 
							</Layout>
 | 
				
			||||||
 | 
						);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default OEM;
 | 
				
			||||||
							
								
								
									
										2
									
								
								src/theme/NotFound.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,2 @@
 | 
				
			|||||||
 | 
					/// <reference types="react" />
 | 
				
			||||||
 | 
					export default function NotFound(): JSX.Element;
 | 
				
			||||||
							
								
								
									
										33
									
								
								src/theme/NotFound.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,33 @@
 | 
				
			|||||||
 | 
					import React from "react";
 | 
				
			||||||
 | 
					import Translate, { translate } from "@docusaurus/Translate";
 | 
				
			||||||
 | 
					import { PageMetadata } from "@docusaurus/theme-common";
 | 
				
			||||||
 | 
					import Layout from "@theme/Layout";
 | 
				
			||||||
 | 
					export default function NotFound() {
 | 
				
			||||||
 | 
						return (
 | 
				
			||||||
 | 
							<>
 | 
				
			||||||
 | 
								<PageMetadata
 | 
				
			||||||
 | 
									title={translate({
 | 
				
			||||||
 | 
										id: "theme.NotFound.title",
 | 
				
			||||||
 | 
										message: "Page Not Found",
 | 
				
			||||||
 | 
									})}
 | 
				
			||||||
 | 
								/>
 | 
				
			||||||
 | 
								<Layout>
 | 
				
			||||||
 | 
									<main className="container margin-vert--xl">
 | 
				
			||||||
 | 
										<div className="row">
 | 
				
			||||||
 | 
											<div className="col col--6 col--offset-3">
 | 
				
			||||||
 | 
												<h1 className="hero__title">
 | 
				
			||||||
 | 
													<Translate
 | 
				
			||||||
 | 
														id="theme.NotFound.title"
 | 
				
			||||||
 | 
														description="The title of the 404 page"
 | 
				
			||||||
 | 
													>
 | 
				
			||||||
 | 
														404 - Page Not Found
 | 
				
			||||||
 | 
													</Translate>
 | 
				
			||||||
 | 
												</h1>
 | 
				
			||||||
 | 
												<img src="/design/chirpy.png" alt='Chirpy' />
 | 
				
			||||||
 | 
											</div>
 | 
				
			||||||
 | 
										</div>
 | 
				
			||||||
 | 
									</main>
 | 
				
			||||||
 | 
								</Layout>
 | 
				
			||||||
 | 
							</>
 | 
				
			||||||
 | 
						);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										65
									
								
								src/utils/apiTypes.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,65 @@
 | 
				
			|||||||
 | 
					export interface Showcase {
 | 
				
			||||||
 | 
						id: string;
 | 
				
			||||||
 | 
						title: string;
 | 
				
			||||||
 | 
						summary: string;
 | 
				
			||||||
 | 
						body: string;
 | 
				
			||||||
 | 
						createdAt: Date;
 | 
				
			||||||
 | 
						updatedAt: Date;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						tags: ShowcaseTag[];
 | 
				
			||||||
 | 
						nodes?: Node[];
 | 
				
			||||||
 | 
						materials?: Material[];
 | 
				
			||||||
 | 
						author?: Author;
 | 
				
			||||||
 | 
						authorId?: string;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export interface ShowcaseTag {
 | 
				
			||||||
 | 
						id: string;
 | 
				
			||||||
 | 
						label: string;
 | 
				
			||||||
 | 
						description: string;
 | 
				
			||||||
 | 
						color: string;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						showcases?: Showcase[];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export interface Node {
 | 
				
			||||||
 | 
						id: string;
 | 
				
			||||||
 | 
						latitude: string;
 | 
				
			||||||
 | 
						longitude: string;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						showcase?: Showcase;
 | 
				
			||||||
 | 
						showcaseId?: string;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export interface Material {
 | 
				
			||||||
 | 
						id: string;
 | 
				
			||||||
 | 
						name: string;
 | 
				
			||||||
 | 
						details: string;
 | 
				
			||||||
 | 
						image: string;
 | 
				
			||||||
 | 
						url: string;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						showcases?: Showcase[];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export interface Author {
 | 
				
			||||||
 | 
						id: string;
 | 
				
			||||||
 | 
						githubUsername: string;
 | 
				
			||||||
 | 
						bio: string;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						showcase?: Showcase[];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export interface DeviceFirmwareResource {
 | 
				
			||||||
 | 
						id: string;
 | 
				
			||||||
 | 
						title: string;
 | 
				
			||||||
 | 
						page_url?: string;
 | 
				
			||||||
 | 
						zip_url?: string;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export interface FirmwareReleases {
 | 
				
			||||||
 | 
						releases: {
 | 
				
			||||||
 | 
							stable: DeviceFirmwareResource[];
 | 
				
			||||||
 | 
							alpha: DeviceFirmwareResource[];
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						pullRequests: DeviceFirmwareResource[];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										1
									
								
								src/utils/breakpoints.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					export const BREAKPOINTS = { sm: 640, md: 768, lg: 1024, xl: 1280 };
 | 
				
			||||||
							
								
								
									
										23
									
								
								src/utils/calculateADC.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,23 @@
 | 
				
			|||||||
 | 
					export default function calculateADC() {
 | 
				
			||||||
 | 
						//const variables
 | 
				
			||||||
 | 
						const BAT_MILLIVOLTS_FULL = 4.2;
 | 
				
			||||||
 | 
						const BAT_MILLIVOLTS_EMPTY = 3.27;
 | 
				
			||||||
 | 
						const BAT_FULL_PERCENT = 1;
 | 
				
			||||||
 | 
						//variable
 | 
				
			||||||
 | 
						const batteryChargePercent =
 | 
				
			||||||
 | 
							parseFloat(
 | 
				
			||||||
 | 
								(<HTMLInputElement>document.getElementById("batteryChargePercent")).value,
 | 
				
			||||||
 | 
							) / 100;
 | 
				
			||||||
 | 
						const operativeAdcMultiplier = parseFloat(
 | 
				
			||||||
 | 
							(<HTMLInputElement>document.getElementById("operativeAdcMultiplier")).value,
 | 
				
			||||||
 | 
						);
 | 
				
			||||||
 | 
						const result =
 | 
				
			||||||
 | 
							(operativeAdcMultiplier *
 | 
				
			||||||
 | 
								((BAT_FULL_PERCENT - 1) * BAT_MILLIVOLTS_EMPTY -
 | 
				
			||||||
 | 
									BAT_FULL_PERCENT * BAT_MILLIVOLTS_FULL)) /
 | 
				
			||||||
 | 
							((batteryChargePercent - 1) * BAT_MILLIVOLTS_EMPTY -
 | 
				
			||||||
 | 
								batteryChargePercent * BAT_MILLIVOLTS_FULL);
 | 
				
			||||||
 | 
						(<HTMLInputElement>(
 | 
				
			||||||
 | 
							document.getElementById("newOperativeAdcMultiplier")
 | 
				
			||||||
 | 
						)).value = result.toFixed(4);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										13
									
								
								src/utils/map.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,13 @@
 | 
				
			|||||||
 | 
					import { Node } from "./apiTypes";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const mapUrl = (nodes: Node[]): string => {
 | 
				
			||||||
 | 
						const width = 900;
 | 
				
			||||||
 | 
						const height = 400;
 | 
				
			||||||
 | 
						const access_token =
 | 
				
			||||||
 | 
							"pk.eyJ1Ijoic2FjaGF3IiwiYSI6ImNrNW9meXozZjBsdW0zbHBjM2FnNnV6cmsifQ.3E4n8eFGD9ZOFo-XDVeZnQ";
 | 
				
			||||||
 | 
						const nodeCoords = nodes.map(
 | 
				
			||||||
 | 
							({ latitude, longitude }) => `pin-l+67ea94(${longitude},${latitude})`,
 | 
				
			||||||
 | 
						);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return `https://api.mapbox.com/styles/v1/mapbox/satellite-v9/static/${nodeCoords}/auto/${width}x${height}@2x?access_token=${access_token}`;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
							
								
								
									
										22
									
								
								src/utils/showcase.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,22 @@
 | 
				
			|||||||
 | 
					export const sortBy = <T>(array: T[], getter: (item: T) => unknown): T[] => {
 | 
				
			||||||
 | 
						const sortedArray = [...array];
 | 
				
			||||||
 | 
						sortedArray.sort((a, b) =>
 | 
				
			||||||
 | 
							getter(a) > getter(b) ? 1 : getter(b) > getter(a) ? -1 : 0,
 | 
				
			||||||
 | 
						);
 | 
				
			||||||
 | 
						return sortedArray;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const difference = <T>(...arrays: T[][]): T[] => {
 | 
				
			||||||
 | 
						return arrays.reduce((a, b) => a.filter((c) => !b.includes(c)));
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const toggleListItem = <T>(list: T[], item: T): T[] => {
 | 
				
			||||||
 | 
						const itemIndex = list.indexOf(item);
 | 
				
			||||||
 | 
						if (itemIndex === -1) {
 | 
				
			||||||
 | 
							return list.concat(item);
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							const newList = [...list];
 | 
				
			||||||
 | 
							newList.splice(itemIndex, 1);
 | 
				
			||||||
 | 
							return newList;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
							
								
								
									
										1
									
								
								src/utils/swr.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					export const fetcher = (url: string) => fetch(url).then((res) => res.json());
 | 
				
			||||||
							
								
								
									
										1
									
								
								static/2.0/CF_logo_horizontal_blktype.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					<svg xmlns="http://www.w3.org/2000/svg" data-name="Layer 1" viewBox="0 0 651.29 94.76"><path d="m143.05 93.42 1.07-3.71c1.27-4.41.8-8.48-1.34-11.48-2-2.76-5.26-4.38-9.25-4.57L58 72.7a1.47 1.47 0 0 1-1.35-2 2 2 0 0 1 1.75-1.34l76.26-1c9-.41 18.84-7.75 22.27-16.71l4.34-11.36a2.68 2.68 0 0 0 .18-1 3.31 3.31 0 0 0-.06-.54 49.67 49.67 0 0 0-95.49-5.14 22.35 22.35 0 0 0-35 23.42A31.73 31.73 0 0 0 .34 93.45a1.47 1.47 0 0 0 1.45 1.27h139.49a1.83 1.83 0 0 0 1.77-1.3Z" style="fill:#f78100"/><path d="M168.22 41.15q-1 0-2.1.06a.88.88 0 0 0-.32.07 1.17 1.17 0 0 0-.76.8l-3 10.26c-1.28 4.41-.81 8.48 1.34 11.48a11.65 11.65 0 0 0 9.24 4.57l16.11 1a1.44 1.44 0 0 1 1.14.62 1.5 1.5 0 0 1 .17 1.37 2 2 0 0 1-1.75 1.34l-16.73 1c-9.09.42-18.88 7.75-22.31 16.7l-1.21 3.16a.9.9 0 0 0 .79 1.22h57.63a1.55 1.55 0 0 0 1.54-1.17 41.34 41.34 0 0 0-39.76-52.48Z" style="fill:#fcad32"/><path d="M273.03 59.66h9.53v26.06h16.67v8.35h-26.2V59.66zM309.11 77v-.09c0-9.88 8-17.9 18.58-17.9s18.48 7.92 18.48 17.8v.1c0 9.88-8 17.89-18.58 17.89s-18.48-7.95-18.48-17.8m27.33 0v-.09c0-5-3.59-9.29-8.85-9.29s-8.7 4.22-8.7 9.19v.1c0 5 3.59 9.29 8.8 9.29s8.75-4.23 8.75-9.2m21.4 2V59.66h9.69v19.12c0 5 2.5 7.33 6.34 7.33s6.34-2.26 6.34-7.08V59.66h9.68v19.07c0 11.11-6.34 16-16.12 16s-15.93-5-15.93-15.73m46.65-19.34h13.27c12.29 0 19.42 7.08 19.42 17v.1c0 9.93-7.23 17.3-19.61 17.3h-13.08Zm13.42 26c5.7 0 9.49-3.15 9.49-8.71v-.09c0-5.51-3.79-8.71-9.49-8.71H414v17.47Zm33.13-26h27.52v8.36h-17.98v5.85h16.27v7.91h-16.27v12.29h-9.54V59.66zm40.8 0h9.53v26.06h16.67v8.35h-26.2V59.66zm51.16-.24h9.19l14.61 34.65h-10.22l-2.51-6.14h-13.28l-2.45 6.14h-10Zm8.35 21.08-3.83-9.78-3.92 9.78Zm27.73-20.84h16.27c5.27 0 8.9 1.38 11.21 3.74a10.64 10.64 0 0 1 3.05 8v.1a10.88 10.88 0 0 1-7.08 10.57l8.21 12h-11l-6.94-10.42h-4.18v10.42h-9.54Zm15.83 16.52c3.25 0 5.12-1.58 5.12-4.08V72c0-2.71-2-4.08-5.17-4.08h-6.24v8.26Zm28.46-16.52h27.68v8.11h-18.24v5.21h16.52v7.52h-16.52v5.46h18.48v8.11h-27.92V59.66zM252.15 81a8.44 8.44 0 0 1-7.88 5.16c-5.22 0-8.8-4.33-8.8-9.29v-.1c0-5 3.49-9.2 8.7-9.2a8.64 8.64 0 0 1 8.18 5.71h10C260.79 65.09 253.6 59 244.27 59c-10.62 0-18.58 8-18.58 17.9v.1c0 9.88 7.86 17.8 18.48 17.8 9.08 0 16.18-5.88 18.05-13.76Z"/></svg>
 | 
				
			||||||
| 
		 After Width: | Height: | Size: 2.1 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								static/2.0/LILYGO.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 347 KiB  | 
							
								
								
									
										1
									
								
								static/2.0/RAK-blue-main.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 11 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								static/2.0/android.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 127 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								static/2.0/background.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 988 KiB  | 
							
								
								
									
										1
									
								
								static/2.0/discord.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					<svg xmlns="http://www.w3.org/2000/svg" width="292" height="80" fill="none" viewBox="0 0 292 80"><g clip-path="url(#a)"><g fill="#5865F2" clip-path="url(#b)"><path d="M61.796 16.494a59.415 59.415 0 0 0-15.05-4.73 44.128 44.128 0 0 0-1.928 4.003c-5.612-.844-11.172-.844-16.68 0a42.783 42.783 0 0 0-1.95-4.002 59.218 59.218 0 0 0-15.062 4.74C1.6 30.9-.981 44.936.31 58.772c6.317 4.717 12.44 7.583 18.458 9.458a45.906 45.906 0 0 0 3.953-6.51 38.872 38.872 0 0 1-6.225-3.03 30.957 30.957 0 0 0 1.526-1.208c12.004 5.615 25.046 5.615 36.906 0 .499.416 1.01.82 1.526 1.208a38.775 38.775 0 0 1-6.237 3.035 45.704 45.704 0 0 0 3.953 6.511c6.025-1.875 12.153-4.74 18.47-9.464 1.515-16.04-2.588-29.947-10.844-42.277Zm-37.44 33.767c-3.603 0-6.558-3.363-6.558-7.46 0-4.096 2.892-7.466 6.559-7.466 3.666 0 6.621 3.364 6.558 7.466.006 4.097-2.892 7.46-6.558 7.46Zm24.237 0c-3.603 0-6.558-3.363-6.558-7.46 0-4.096 2.892-7.466 6.558-7.466 3.667 0 6.622 3.364 6.558 7.466 0 4.097-2.891 7.46-6.558 7.46ZM98.03 26.17h15.663c3.776 0 6.966.604 9.583 1.806 2.61 1.201 4.567 2.877 5.864 5.022 1.296 2.145 1.95 4.6 1.95 7.367 0 2.707-.677 5.163-2.031 7.36-1.354 2.204-3.414 3.944-6.185 5.228-2.771 1.283-6.203 1.928-10.305 1.928h-14.54V26.17Zm14.378 21.414c2.542 0 4.499-.65 5.864-1.945 1.366-1.301 2.049-3.071 2.049-5.316 0-2.08-.609-3.739-1.825-4.98-1.216-1.243-3.058-1.87-5.52-1.87h-4.9v14.111h4.332Zm42.133 7.262c-2.169-.575-4.126-1.407-5.864-2.503v-6.81c1.314 1.038 3.075 1.893 5.284 2.567 2.209.668 4.344 1.002 6.409 1.002.964 0 1.693-.128 2.186-.386.494-.258.741-.569.741-.926 0-.41-.132-.75-.402-1.026-.27-.275-.792-.504-1.566-.697l-4.82-1.108c-2.76-.656-4.717-1.565-5.881-2.73-1.165-1.161-1.745-2.685-1.745-4.572 0-1.588.505-2.965 1.527-4.143 1.015-1.178 2.461-2.087 4.337-2.725 1.877-.645 4.068-.967 6.587-.967 2.249 0 4.309.246 6.186.738 1.876.492 3.425 1.12 4.659 1.887v6.44c-1.263-.767-2.709-1.37-4.361-1.828a19.138 19.138 0 0 0-5.084-.674c-2.519 0-3.775.44-3.775 1.313 0 .41.195.715.585.92.39.205 1.107.416 2.146.639l4.016.738c2.623.463 4.579 1.278 5.864 2.438 1.286 1.16 1.928 2.878 1.928 5.152 0 2.49-1.061 4.465-3.19 5.93-2.129 1.465-5.147 2.198-9.06 2.198a26.36 26.36 0 0 1-6.707-.867Zm28.437-.862c-2.3-1.149-4.039-2.708-5.198-4.677-1.159-1.969-1.744-4.184-1.744-6.645 0-2.462.602-4.665 1.807-6.605 1.205-1.94 2.972-3.464 5.302-4.571 2.329-1.108 5.112-1.659 8.354-1.659 4.016 0 7.35.862 10.001 2.585v7.507c-.935-.656-2.026-1.19-3.271-1.6-1.245-.41-2.576-.615-3.999-.615-2.49 0-4.435.463-5.841 1.395-1.406.931-2.111 2.144-2.111 3.65 0 1.477.682 2.685 2.048 3.634 1.366.944 3.345 1.418 5.944 1.418 1.337 0 2.657-.2 3.959-.592 1.297-.398 2.416-.885 3.351-1.459v7.261c-2.943 1.805-6.357 2.707-10.242 2.707-3.27-.011-6.059-.586-8.36-1.734Zm28.54 0c-2.318-1.148-4.085-2.72-5.302-4.718-1.216-1.998-1.83-4.225-1.83-6.686 0-2.462.608-4.66 1.83-6.587 1.222-1.928 2.978-3.44 5.285-4.536 2.3-1.096 5.049-1.641 8.233-1.641 3.185 0 5.933.545 8.234 1.64 2.301 1.097 4.057 2.597 5.262 4.513 1.205 1.917 1.807 4.114 1.807 6.605 0 2.461-.602 4.688-1.807 6.687-1.205 1.998-2.967 3.569-5.285 4.717-2.318 1.149-5.055 1.723-8.216 1.723-3.162 0-5.899-.568-8.211-1.717Zm12.204-7.279c.976-.996 1.469-2.314 1.469-3.955s-.488-2.948-1.469-3.915c-.975-.973-2.307-1.46-3.993-1.46-1.716 0-3.059.487-4.04 1.46-.975.973-1.463 2.274-1.463 3.915 0 1.64.488 2.96 1.463 3.956.976.996 2.324 1.5 4.04 1.5 1.686-.006 3.018-.504 3.993-1.5ZM259.17 31.34v8.86c-1.021-.685-2.341-1.025-3.976-1.025-2.141 0-3.793.662-4.941 1.986-1.153 1.325-1.727 3.388-1.727 6.177v7.548h-9.84V30.888h9.64v7.63c.533-2.79 1.4-4.846 2.593-6.176 1.188-1.325 2.725-1.987 4.596-1.987 1.417 0 2.634.328 3.655.985Zm32.694-5.99v29.537h-9.841v-5.374c-.832 2.022-2.094 3.563-3.792 4.618-1.699 1.049-3.799 1.576-6.289 1.576-2.226 0-4.165-.55-5.824-1.658-1.658-1.108-2.937-2.626-3.838-4.554-.895-1.928-1.349-4.108-1.349-6.546-.028-2.514.448-4.77 1.429-6.769.976-1.998 2.358-3.557 4.137-4.676 1.779-1.12 3.81-1.682 6.088-1.682 4.688 0 7.832 2.08 9.438 6.235V25.35h9.841Zm-11.309 21.191c1.004-.996 1.503-2.29 1.503-3.873 0-1.53-.488-2.778-1.463-3.733-.976-.956-2.313-1.436-3.994-1.436-1.658 0-2.983.486-3.976 1.46-.993.972-1.486 2.232-1.486 3.79 0 1.56.493 2.831 1.486 3.816.993.984 2.301 1.477 3.936 1.477 1.658-.006 2.989-.504 3.994-1.5ZM139.382 33.443c2.709 0 4.906-2.015 4.906-4.5 0-2.486-2.197-4.501-4.906-4.501-2.71 0-4.906 2.015-4.906 4.5 0 2.486 2.196 4.501 4.906 4.501Zm-4.91 3.101c3.006 1.324 6.736 1.383 9.811 0v18.471h-9.811V36.544Z"/></g></g><defs><clipPath id="a"><path fill="#fff" d="M0 11.765h292v56.47H0z"/></clipPath><clipPath id="b"><path fill="#fff" d="M0 11.765h292v56.47H0z"/></clipPath></defs></svg>
 | 
				
			||||||
| 
		 After Width: | Height: | Size: 4.5 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								static/2.0/ios.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 1.2 MiB  | 
							
								
								
									
										1
									
								
								static/2.0/opencollectivelogo.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					<svg xmlns="http://www.w3.org/2000/svg" width="457" height="60" viewBox="0 0 457 60"><g fill="none" fill-rule="evenodd"><path fill="#7FADF2" d="M34.62 18.179C36.75 21.249 38 24.979 38 29s-1.25 7.75-3.38 10.821L29.697 34.9a12.16 12.16 0 0 0 1.517-5.9c0-2.14-.55-4.15-1.516-5.9l4.921-4.921Zm-4.8-4.799-4.92 4.922a12.16 12.16 0 0 0-5.9-1.516c-6.746 0-12.214 5.468-12.214 12.214S12.254 41.214 19 41.214c2.14 0 4.15-.55 5.9-1.516l4.921 4.921A18.912 18.912 0 0 1 19 48C8.507 48 0 39.493 0 29s8.507-19 19-19c4.021 0 7.75 1.25 10.821 3.38Z"/><path fill="#B8D3F4" d="M34.62 18.179C36.75 21.249 38 24.979 38 29s-1.25 7.75-3.38 10.821L29.697 34.9a12.16 12.16 0 0 0 1.517-5.9c0-2.14-.55-4.15-1.516-5.9l4.921-4.921Z"/><path fill="#515F71" d="M110.7 13.6c-3.7 0-7.2 1.4-9.8 3.6v-2.3c0-.6-.5-1-1-1h-3.4c-.6 0-1 .5-1 1v43.7c0 .5.4 1 1 1h3.5c.5 0 1-.4 1-1V40.3c2.6 2.2 6.1 3.6 9.8 3.6 8.4 0 15.2-6.8 15.2-15.2-.2-8.4-7-15.1-15.3-15.1Zm0 24.8c-5.4 0-9.7-4.4-9.7-9.7 0-5.4 4.4-9.7 9.7-9.7 5.4 0 9.7 4.4 9.7 9.7 0 5.4-4.4 9.7-9.7 9.7Zm65.9-24.8c-3.7 0-7.1 1.3-9.7 3.5v-1.3c0-1.1-.9-2-2-2h-1.5c-1.1 0-2 .9-2 2v26.3c0 .8.7 1.5 1.5 1.5h2.5c.8 0 1.5-.7 1.5-1.5V29.6c0-5.4 4.4-10.6 9.7-10.6 3.5 0 9.7 1.9 9.7 10.6v12.5c0 .8.7 1.5 1.5 1.5h2.5c.8 0 1.5-.7 1.5-1.5V29.5c0-13.2-10.4-15.9-15.2-15.9Zm-18.4 11.9c-1.5-7.1-8-12.3-15.6-11.9-7.6.4-13.8 6.4-14.3 14-.6 8.9 6.4 16.3 15.1 16.3 5.9 0 11-3.3 13.5-8.2.4-.7-.1-1.6-.9-1.8l-3-.6c-.5-.1-1 .1-1.3.6-1.7 2.7-4.8 4.6-8.2 4.6-3 0-5.7-1.4-7.5-3.5l17.2-7.2 5-2.3Zm-24.4 4.4c0-.4-.1-.8-.1-1.2 0-5.4 4.4-9.7 9.7-9.7 3 0 5.8 1.4 7.5 3.6l-17.1 7.3ZM77.3 13.4c-8.4 0-15.2 6.8-15.2 15.2 0 8.4 6.8 15.2 15.2 15.2 8.4 0 15.2-6.8 15.2-15.2 0-8.4-6.8-15.2-15.2-15.2Zm0 24.9c-5.4 0-9.7-4.4-9.7-9.7 0-5.4 4.4-9.7 9.7-9.7 5.4 0 9.7 4.4 9.7 9.7.1 5.3-4.3 9.7-9.7 9.7Zm181.4-25c-8.4 0-15.2 6.8-15.2 15.2 0 8.4 6.8 15.2 15.2 15.2 8.4 0 15.2-6.8 15.2-15.2 0-8.4-6.8-15.2-15.2-15.2Zm0 24.9c-5.4 0-9.7-4.4-9.7-9.7 0-5.4 4.4-9.7 9.7-9.7 5.4 0 9.7 4.4 9.7 9.7 0 5.3-4.3 9.7-9.7 9.7ZM390.6 4.3h-3.1c-.7 0-1.2.5-1.2 1.2v3.1c0 .7.5 1.2 1.2 1.2h3.1c.7 0 1.2-.5 1.2-1.2V5.5c0-.7-.6-1.2-1.2-1.2Zm63.9 29.4-3.6-.7c-.4-.1-.8.1-1 .5-1.7 2.8-4.8 4.7-8.3 4.7-3 0-5.7-1.4-7.5-3.5l17.2-7.2 5.2-2.2c-1.5-7.1-8-12.3-15.6-11.9-7.6.4-13.8 6.5-14.3 14.1-.6 8.9 6.4 16.3 15.1 16.3 6 0 11.2-3.5 13.6-8.5.2-.8-.2-1.5-.8-1.6Zm-22.7-5.3c0-5.4 4.4-9.7 9.7-9.7 3 0 5.8 1.4 7.5 3.6l-17.2 7.3v-1.2ZM332 25.2c-1.5-7.1-8-12.3-15.6-11.9-7.6.4-13.8 6.5-14.3 14.1-.6 8.9 6.4 16.3 15.1 16.3 6 0 11.2-3.5 13.7-8.6.3-.6-.1-1.3-.7-1.4l-3.6-.7c-.4-.1-.8.1-1 .5-1.7 2.8-4.8 4.7-8.3 4.7-3 0-5.7-1.4-7.5-3.5l17.2-7.2 5-2.3Zm-24.5 4.4c0-.4-.1-.8-.1-1.2 0-5.4 4.4-9.7 9.7-9.7 3 0 5.8 1.4 7.5 3.6l-17.1 7.3ZM283.2.7h-3.6c-.5 0-.9.4-.9.9v40.7c0 .5.4 1 1 1h3.5c.5 0 1-.4 1-1V1.6c0-.5-.5-.9-1-.9Zm12.3 0h-3.6c-.5 0-.9.4-.9.9v40.7c0 .5.4 1 1 1h3.5c.5 0 1-.4 1-1V1.6c-.1-.5-.5-.9-1-.9Zm95.1 12.7h-3.1c-.7 0-1.2.5-1.2 1.2v27.6c0 .7.5 1.2 1.2 1.2h3.1c.7 0 1.2-.5 1.2-1.2V14.5c0-.6-.6-1.1-1.2-1.1Zm-10.2 0h-3.9c-.4 0-.8-.4-.8-.8V1.5c0-.4-.4-.8-.8-.8H371c-.4 0-.8.4-.8.8v11.1c0 .4-.4.8-.8.8h-3.9c-.4 0-.8.4-.8.8V18c0 .4.4.8.8.8h3.9c.4 0 .8.4.8.8v22.7c0 .6.5 1 1 1h3.4c.6 0 1-.5 1-1V19.6c0-.4.4-.8.8-.8h3.9c.4 0 .8-.4.8-.8v-3.9c.1-.4-.2-.7-.7-.7Zm-21.6 22.1c-.4-.4-1.1-.4-1.5 0-1.8 1.7-4.1 2.7-6.8 2.7-5.7 0-10.3-5-9.7-10.8.5-4.5 4.2-8.1 8.7-8.6 2.8-.3 5.5.7 7.4 2.4.6.5 1.5.5 2.1-.1l1.7-1.7c.6-.6.6-1.6 0-2.2-2.9-2.7-6.9-4.2-11.2-3.9-7.7.5-13.9 6.9-14.2 14.7-.3 8.6 6.6 15.6 15.2 15.6 4.1 0 7.9-1.6 10.6-4.3.4-.4.4-1.1 0-1.5l-2.3-2.3Zm-119.7 0c-.4-.4-1.1-.4-1.5 0-1.8 1.7-4.1 2.7-6.8 2.7-5.7 0-10.3-5-9.7-10.8.5-4.5 4.2-8.1 8.7-8.6 2.8-.3 5.5.7 7.4 2.4.6.5 1.5.5 2.1-.1l1.7-1.7c.6-.6.6-1.6 0-2.2-2.9-2.7-6.9-4.2-11.2-3.9-7.7.5-13.9 6.9-14.2 14.7-.3 8.6 6.6 15.6 15.2 15.6 4.1 0 7.9-1.6 10.6-4.3.4-.4.4-1.1 0-1.5l-2.3-2.3ZM424 13.7h-4.9c-.1 0-.2.1-.2.2l-8 23.5c-.1.2-.4.2-.4 0l-8-23.5c0-.1-.1-.2-.2-.2h-4.9c-.2 0-.3.2-.2.3l9.9 29.1c0 .1.1.2.2.2h6.8c.1 0 .2-.1.2-.2l9.9-29.1c.1-.1 0-.3-.2-.3Z"/></g></svg>
 | 
				
			||||||
| 
		 After Width: | Height: | Size: 3.9 KiB  | 
							
								
								
									
										1
									
								
								static/2.0/typelogo.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:1.5" viewBox="0 0 1115 116"><path d="m81.582 577.266 66.954-98.462" style="fill:none;stroke:#fff;stroke-width:14.11px" transform="translate(-75.985 -483.202) scale(1.02332)"/><path d="m81.582 577.266 66.954-98.462" style="fill:none;stroke:#fff;stroke-width:14.86px" transform="matrix(1.01019 0 0 1.0102 852.95 -475.627)"/><text x="640.988" y="399.072" style="fill:#fff;font-family:"ArialMT","Arial",sans-serif;font-size:12px" transform="matrix(12.6568 0 0 12.68749 -7898.028 -4950.898)">ESHT</text><path d="m187.032 410.85 63.864-93.658 64.011 93.51" style="fill:none;stroke:#fff;stroke-width:13.85px" transform="translate(-120.199 -314.73) scale(1.02696)"/><path d="m187.032 410.85 63.864-93.658 64.011 93.51" style="fill:none;stroke:#fff;stroke-width:13.85px" transform="translate(417.633 -313.199) scale(1.02696)"/><text style="fill:#fff;font-family:"ArialMT","Arial",sans-serif;font-size:252.715px" transform="matrix(.601 0 0 .60246 750.004 112.652)">ST</text><text style="fill:#fff;font-family:"ArialMT","Arial",sans-serif;font-size:252.715px" transform="matrix(.601 0 0 .60246 1008.532 112.998)">C</text></svg>
 | 
				
			||||||
| 
		 After Width: | Height: | Size: 1.3 KiB  | 
							
								
								
									
										1
									
								
								static/2.0/vercel-logotype-dark.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					<svg xmlns="http://www.w3.org/2000/svg" width="4438" height="1000" fill="none" viewBox="0 0 4438 1000"><path fill="#000" d="M2223.75 250c-172.5 0-296.88 112.5-296.88 281.25s139.85 281.25 312.51 281.25c104.21 0 196.09-41.25 252.96-110.781l-119.53-69.063c-31.56 34.532-79.53 54.688-133.43 54.688-74.85 0-138.44-39.063-162.04-101.563h437.82c3.43-17.5 5.47-35.625 5.47-54.687C2520.63 362.5 2396.41 250 2223.75 250Zm-147.66 226.562C2095.62 414.219 2149.06 375 2223.75 375c74.84 0 128.28 39.219 147.66 101.562h-295.32Zm-35.31-398.437-432.97 750-433.12-750h162.34l270.63 468.75 270.62-468.75h162.5ZM577.344 0l577.346 1000H0L577.344 0ZM3148.75 531.25C3148.75 625 3210 687.5 3305 687.5c64.38 0 112.66-29.219 137.5-76.875l120 69.219C3512.81 762.656 3419.69 812.5 3305 812.5c-172.66 0-296.87-112.5-296.87-281.25S3132.5 250 3305 250c114.69 0 207.66 49.844 257.5 132.656l-120 69.219C3417.66 404.219 3369.38 375 3305 375c-94.84 0-156.25 62.5-156.25 156.25ZM4437.5 78.125v718.75h-140.62V78.125h140.62ZM3906.25 250c-172.5 0-296.87 112.5-296.87 281.25s140 281.25 312.5 281.25c104.21 0 196.09-41.25 252.96-110.781l-119.53-69.063c-31.56 34.532-79.53 54.688-133.43 54.688-74.85 0-138.44-39.063-162.04-101.563h437.82c3.43-17.5 5.46-35.625 5.46-54.687C4203.12 362.5 4078.91 250 3906.25 250Zm-147.66 226.562C3778.13 414.219 3831.41 375 3906.25 375s128.28 39.219 147.66 101.562h-295.32Zm-797.34-210.937v151.406c-15.62-4.531-32.19-7.656-50-7.656-90.78 0-156.25 62.5-156.25 156.25v231.25h-140.62v-531.25H2755v143.75c0-79.375 92.34-143.75 206.25-143.75Z"/></svg>
 | 
				
			||||||
| 
		 After Width: | Height: | Size: 1.5 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								static/2.0/webUI.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 410 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								static/img/amazon-fire-button.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 31 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								static/img/dead-banner.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 15 KiB  | 
							
								
								
									
										1
									
								
								static/img/efficiency.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 10 KiB  | 
							
								
								
									
										1
									
								
								static/img/homepage/Discord-Logo-White.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					<svg xmlns="http://www.w3.org/2000/svg" width="71" height="55" fill="none" viewBox="0 0 71 55"><g clip-path="url(#a)"><path fill="#fff" d="M60.105 4.898A58.55 58.55 0 0 0 45.653.415a.22.22 0 0 0-.233.11 40.784 40.784 0 0 0-1.8 3.697c-5.456-.817-10.886-.817-16.23 0-.485-1.164-1.201-2.587-1.828-3.697a.228.228 0 0 0-.233-.11 58.386 58.386 0 0 0-14.451 4.483.207.207 0 0 0-.095.082C1.578 18.73-.944 32.144.293 45.39a.244.244 0 0 0 .093.167c6.073 4.46 11.955 7.167 17.729 8.962a.23.23 0 0 0 .249-.082 42.08 42.08 0 0 0 3.627-5.9.225.225 0 0 0-.123-.312 38.772 38.772 0 0 1-5.539-2.64.228.228 0 0 1-.022-.378 31.17 31.17 0 0 0 1.1-.862.22.22 0 0 1 .23-.03c11.619 5.304 24.198 5.304 35.68 0a.219.219 0 0 1 .233.027c.356.293.728.586 1.103.865a.228.228 0 0 1-.02.378 36.384 36.384 0 0 1-5.54 2.637.227.227 0 0 0-.121.315 47.249 47.249 0 0 0 3.624 5.897.225.225 0 0 0 .249.084c5.801-1.794 11.684-4.502 17.757-8.961a.228.228 0 0 0 .092-.164c1.48-15.315-2.48-28.618-10.497-40.412a.18.18 0 0 0-.093-.084Zm-36.38 32.427c-3.497 0-6.38-3.211-6.38-7.156 0-3.944 2.827-7.156 6.38-7.156 3.583 0 6.438 3.24 6.382 7.156 0 3.945-2.827 7.156-6.381 7.156Zm23.593 0c-3.498 0-6.38-3.211-6.38-7.156 0-3.944 2.826-7.156 6.38-7.156 3.582 0 6.437 3.24 6.38 7.156 0 3.945-2.798 7.156-6.38 7.156Z"/></g><defs><clipPath id="a"><path fill="#fff" d="M0 0h71v55H0z"/></clipPath></defs></svg>
 | 
				
			||||||
| 
		 After Width: | Height: | Size: 1.3 KiB  | 
							
								
								
									
										1
									
								
								static/img/homepage/Discourse-Logo-White.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -1 104 106"><path d="M51.87 0C23.71 0 0 22.83 0 51v52.81l51.86-.05c28.16 0 51-23.71 51-51.87S80 0 51.87 0Z" style="fill:#231f20"/><path d="M52.37 19.74a31.62 31.62 0 0 0-27.79 46.67l-5.72 18.4 20.54-4.64a31.61 31.61 0 1 0 13-60.43Z" style="fill:#fff9ae"/><path d="M77.45 32.12a31.6 31.6 0 0 1-38.05 48l-20.54 4.7 20.91-2.47a31.6 31.6 0 0 0 37.68-50.23Z" style="fill:#00aeef"/><path d="M71.63 26.29A31.6 31.6 0 0 1 38.8 78l-19.94 6.82 20.54-4.65a31.6 31.6 0 0 0 32.23-53.88Z" style="fill:#00a94f"/><path d="M26.47 67.11a31.61 31.61 0 0 1 51-35 31.61 31.61 0 0 0-52.89 34.3l-5.72 18.4Z" style="fill:#f15d22"/><path d="M24.58 66.41a31.61 31.61 0 0 1 47.05-40.12 31.61 31.61 0 0 0-49 39.63l-3.76 18.9Z" style="fill:#e31b23"/></svg>
 | 
				
			||||||
| 
		 After Width: | Height: | Size: 778 B  | 
							
								
								
									
										1
									
								
								static/img/homepage/GitHub-Logo-White.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					<svg xmlns="http://www.w3.org/2000/svg" width="1024" height="1024" fill="none" viewBox="0 0 1024 1024"><path fill="#1B1F23" fill-rule="evenodd" d="M512 0C229.12 0 0 229.12 0 512c0 226.56 146.56 417.92 350.08 485.76 25.6 4.48 35.2-10.88 35.2-24.32 0-12.16-.64-52.48-.64-95.36-128.64 23.68-161.92-31.36-172.16-60.16-5.76-14.72-30.72-60.16-52.48-72.32-17.92-9.6-43.52-33.28-.64-33.92 40.32-.64 69.12 37.12 78.72 52.48 46.08 77.44 119.68 55.68 149.12 42.24 4.48-33.28 17.92-55.68 32.64-68.48-113.92-12.8-232.96-56.96-232.96-252.8 0-55.68 19.84-101.76 52.48-137.6-5.12-12.8-23.04-65.28 5.12-135.68 0 0 42.88-13.44 140.8 52.48 40.96-11.52 84.48-17.28 128-17.28 43.52 0 87.04 5.76 128 17.28 97.92-66.56 140.8-52.48 140.8-52.48 28.16 70.4 10.24 122.88 5.12 135.68 32.64 35.84 52.48 81.28 52.48 137.6 0 196.48-119.68 240-233.6 252.8 18.56 16 34.56 46.72 34.56 94.72 0 68.48-.64 123.52-.64 140.8 0 13.44 9.6 29.44 35.2 24.32C877.44 929.92 1024 737.92 1024 512 1024 229.12 794.88 0 512 0Z" clip-rule="evenodd"/></svg>
 | 
				
			||||||
| 
		 After Width: | Height: | Size: 1006 B  | 
							
								
								
									
										1
									
								
								static/img/homepage/Instagram_Glyph_Gradient.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 45 KiB  | 
							
								
								
									
										1
									
								
								static/img/homepage/Reddit-Logo-White.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					<svg xmlns="http://www.w3.org/2000/svg" viewBox="85.45 80.45 170.9 170.9"><path d="M227.9 170.9c0-6.9-5.6-12.5-12.5-12.5-3.4 0-6.4 1.3-8.6 3.5-8.5-6.1-20.3-10.1-33.3-10.6l5.7-26.7 18.5 3.9c.2 4.7 4.1 8.5 8.9 8.5 4.9 0 8.9-4 8.9-8.9s-4-8.9-8.9-8.9c-3.5 0-6.5 2-7.9 5l-20.7-4.4c-.6-.1-1.2 0-1.7.3s-.8.8-1 1.4l-6.3 29.8c-13.3.4-25.2 4.3-33.8 10.6-2.2-2.1-5.3-3.5-8.6-3.5-6.9 0-12.5 5.6-12.5 12.5 0 5.1 3 9.4 7.4 11.4-.2 1.2-.3 2.5-.3 3.8 0 19.2 22.3 34.7 49.9 34.7s49.9-15.5 49.9-34.7c0-1.3-.1-2.5-.3-3.7 4.1-2 7.2-6.4 7.2-11.5zm-85.5 8.9c0-4.9 4-8.9 8.9-8.9s8.9 4 8.9 8.9-4 8.9-8.9 8.9-8.9-4-8.9-8.9zm49.7 23.5c-6.1 6.1-17.7 6.5-21.1 6.5-3.4 0-15.1-.5-21.1-6.5-.9-.9-.9-2.4 0-3.3.9-.9 2.4-.9 3.3 0 3.8 3.8 12 5.2 17.9 5.2s14-1.4 17.9-5.2c.9-.9 2.4-.9 3.3 0 .7 1 .7 2.4-.2 3.3zm-1.6-14.6c-4.9 0-8.9-4-8.9-8.9s4-8.9 8.9-8.9 8.9 4 8.9 8.9-4 8.9-8.9 8.9z" style="fill:#fff"/></svg>
 | 
				
			||||||
| 
		 After Width: | Height: | Size: 875 B  | 
							
								
								
									
										1
									
								
								static/img/homepage/Twitter-Logo-White.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" style="enable-background:new 0 0 400 400" viewBox="0 0 400 400"><path d="M400 200c0 110.5-89.5 200-200 200S0 310.5 0 200 89.5 0 200 0s200 89.5 200 200zM163.4 305.5c88.7 0 137.2-73.5 137.2-137.2 0-2.1 0-4.2-.1-6.2 9.4-6.8 17.6-15.3 24.1-25-8.6 3.8-17.9 6.4-27.7 7.6 10-6 17.6-15.4 21.2-26.7-9.3 5.5-19.6 9.5-30.6 11.7-8.8-9.4-21.3-15.2-35.2-15.2-26.6 0-48.2 21.6-48.2 48.2 0 3.8.4 7.5 1.3 11-40.1-2-75.6-21.2-99.4-50.4-4.1 7.1-6.5 15.4-6.5 24.2 0 16.7 8.5 31.5 21.5 40.1-7.9-.2-15.3-2.4-21.8-6v.6c0 23.4 16.6 42.8 38.7 47.3-4 1.1-8.3 1.7-12.7 1.7-3.1 0-6.1-.3-9.1-.9 6.1 19.2 23.9 33.1 45 33.5-16.5 12.9-37.3 20.6-59.9 20.6-3.9 0-7.7-.2-11.5-.7 21.1 13.8 46.5 21.8 73.7 21.8" style="fill:#fff"/></svg>
 | 
				
			||||||
| 
		 After Width: | Height: | Size: 761 B  | 
							
								
								
									
										1
									
								
								static/img/homepage/YouTube-Logo-White.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					<svg xmlns="http://www.w3.org/2000/svg" width="1200" height="800" viewBox="-35.2 -41.333 305.067 248"><path fill="#fff" d="M93.333 117.559V47.775l61.334 34.893zm136.43-91.742c-2.699-10.162-10.651-18.165-20.747-20.881C190.716 0 117.333 0 117.333 0S43.951 0 25.651 4.936C15.555 7.652 7.603 15.655 4.904 25.817 0 44.236 0 82.667 0 82.667s0 38.429 4.904 56.849c2.699 10.163 10.65 18.165 20.747 20.883 18.3 4.934 91.682 4.934 91.682 4.934s73.383 0 91.683-4.934c10.096-2.718 18.048-10.72 20.747-20.883 4.904-18.42 4.904-56.85 4.904-56.85s0-38.43-4.904-56.849"/></svg>
 | 
				
			||||||
| 
		 After Width: | Height: | Size: 561 B  | 
							
								
								
									
										1
									
								
								static/img/homepage/battery.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					<svg xmlns="http://www.w3.org/2000/svg" width="1000" height="1000" viewBox="150 150 650 650"><g stroke-width=".948"><path fill="#4d4d4d" d="M247.5 596.333H657V353.667H247.5zM277.833 384h348.834v182H277.833z"/><path fill="#67ea94" d="M298.394 405.745h307.722v138.52H298.394z"/><path fill="#4d4d4d" d="M672.167 424.448H702.5v101.114h-30.333z"/></g></svg>
 | 
				
			||||||
| 
		 After Width: | Height: | Size: 352 B  | 
							
								
								
									
										1
									
								
								static/img/homepage/encryption.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					<svg xmlns="http://www.w3.org/2000/svg" width="1000" height="1000" viewBox="150 150 650 650"><path fill="#4d4d4d" d="M604.283 369.655h-72.28V284.62a102.042 102.042 0 1 0-204.083 0v85.035h-72.28a12.755 12.755 0 0 0-12.755 12.755v297.622a12.755 12.755 0 0 0 12.755 12.755h348.643a12.755 12.755 0 0 0 12.755-12.755V382.41a12.755 12.755 0 0 0-12.755-12.755zm-112.671 0h-123.3v-85.832a61.65 61.65 0 1 1 123.3 0z"/><path fill="#eab167" stroke="#4d4d4d" stroke-width="8.5" d="M540.019 526.745c0 10.204 0 20.094 3.218 29.356-33.831 39.718-131.477 152.67-131.477 152.67l2.276 28.494s27.316 25.903 31.398 21.978c12.088-11.774 19.466-19.78 19.466-19.78l5.683-34.027 36.978-2.724 2.967-36.735 38.957-.746.384-39.317 41.359 1.648 7.064-14.788c12.167 5.259 23.234 7.378 37.442 7.378 53.768 0 97.332-41.915 97.332-93.564 0-51.649-43.596-93.408-97.364-93.408s-95.683 41.916-95.683 93.565zm148.156-18.21a30.495 30.495 0 1 1-30.495-30.495 30.463 30.463 0 0 1 30.495 30.494z"/></svg>
 | 
				
			||||||
| 
		 After Width: | Height: | Size: 964 B  | 
							
								
								
									
										1
									
								
								static/img/homepage/extendable.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					<svg xmlns="http://www.w3.org/2000/svg" width="1000" height="1000" viewBox="150 150 650 650"><path fill="#67ea94" stroke="#4d4d4d" stroke-linecap="round" stroke-linejoin="round" stroke-width="15" d="M626.18 465.506h-26.524a1.918 1.918 0 0 1-1.918-1.918v-74.065a37.263 37.263 0 0 0-37.262-37.263H486.41a1.918 1.918 0 0 1-1.918-1.917V323.82c0-26.025-20.616-47.81-46.64-48.262a47.494 47.494 0 0 0-48.329 47.475v27.31a1.918 1.918 0 0 1-1.918 1.917H313.54a38.106 38.106 0 0 0-37.991 37.992v67.487a1.918 1.918 0 0 0 1.918 1.918h25.804c28.162 0 51.473 24.432 51.866 52.595.403 28.642-22.543 54.8-51.1 54.8h-26.57a1.918 1.918 0 0 0-1.918 1.919v67.487a38.106 38.106 0 0 0 37.991 37.99h67.487a1.918 1.918 0 0 0 1.918-1.917v-20.07c0-29.035 23.733-54.033 52.74-54.714 28.862-.671 54.656 19.475 54.656 48.213v26.571a1.918 1.918 0 0 0 1.918 1.918h68.216a37.263 37.263 0 0 0 37.262-37.263v-74.793a1.918 1.918 0 0 1 1.918-1.918h27.31c26.494 0 47.484-21.738 47.484-48.329s-22.246-46.64-48.27-46.64z"/></svg>
 | 
				
			||||||
| 
		 After Width: | Height: | Size: 990 B  | 
							
								
								
									
										
											BIN
										
									
								
								static/img/homepage/f_logo_RGB-White_1024.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 47 KiB  | 
							
								
								
									
										1
									
								
								static/img/homepage/messages.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					<svg xmlns="http://www.w3.org/2000/svg" width="1000" height="1000" viewBox="150 150 650 650"><path fill="#eab167" stroke="#4d4d4d" stroke-linejoin="round" stroke-width="29.792" d="M585.204 337.464v148.4A52.285 52.285 0 0 1 533.068 538H379.313a7.448 7.448 0 0 0-4.777 1.73l-9.228 7.694v20.928a52.285 52.285 0 0 0 52.136 52.136h153.755a7.448 7.448 0 0 1 4.775 1.73l87.254 72.75v-74.48h37.24a52.285 52.285 0 0 0 52.136-52.136V389.6a52.285 52.285 0 0 0-52.136-52.136z"/><path fill="none" stroke="#4d4d4d" stroke-linejoin="round" stroke-width="29.792" d="M532.556 255.034H249.532a52.285 52.285 0 0 0-52.136 52.136v178.752a52.285 52.285 0 0 0 52.136 52.136h37.24v74.48l87.253-72.748a7.448 7.448 0 0 1 4.776-1.732h153.755a52.285 52.285 0 0 0 52.136-52.136V307.17a52.285 52.285 0 0 0-52.136-52.136z"/><g fill="#4d4d4d"><circle cx="301.668" cy="396.546" r="29.792" fill="#eab167"/><circle cx="391.044" cy="396.546" r="29.792" fill="#eab167"/><circle cx="480.42" cy="396.546" r="29.792" fill="#eab167"/></g></svg>
 | 
				
			||||||
| 
		 After Width: | Height: | Size: 1003 B  | 
							
								
								
									
										1
									
								
								static/img/homepage/opensource.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					<svg xmlns="http://www.w3.org/2000/svg" width="1000" height="1000" viewBox="150 150 650 650" transform="matrix(1, 0, 0, 1, 0, 0)"><g stroke-width=".65" transform="matrix(-2403.8462 0 0 0 -624628.82 150)"><circle cx="-259.908" cy="348.214" r="72.8" fill="#eab167"/><path d="M-259.908 441.814c-45.123 0-135.2 27.872-135.2 83.2v41.6h270.4v-41.6c0-55.328-90.077-83.2-135.2-83.2z" fill="#eab167"/></g><g fill="#67ea94" transform="translate(-72.894 73.325)"><circle cx="809.715" cy="368.657" r="23.734" fill="#eab167"/><circle cx="682.328" cy="210.171" r="23.734" fill="#eab167"/><circle cx="682.328" cy="369.754" r="23.734" fill="#eab167"/></g><g fill="#4d4d4d" stroke-width=".65" transform="translate(174.183 59.196) scale(1.42001)"><circle cx="94.257" cy="296.297" r="46.8" fill="#eab167"/><path d="M147.557 369.097c-18.304-9.295-38.506-13-53.3-13-28.977 0-88.4 17.771-88.4 53.3v27.3h97.5v-10.445c0-12.35 5.2-24.733 14.3-35.055 7.26-8.242 17.426-15.892 29.9-22.1z" fill="#eab167"/><path d="M216.457 363.897c-33.846 0-101.4 20.904-101.4 62.4v31.2h202.8v-31.2c0-41.496-67.555-62.4-101.4-62.4z" fill="#eab167"/><circle cx="216.457" cy="285.897" r="57.2" fill="#eab167"/></g><path fill="#4d4d4d" d="M641.245 283.601a31.564 31.564 0 1 0-47.839 27.032v103.47a31.564 31.564 0 1 0 31.564 0V311.22a31.593 31.593 0 0 0 16.275-27.619zm-31.564-15.781A15.782 15.782 0 1 1 593.9 283.6a15.782 15.782 0 0 1 15.782-15.781zm-.493 189.382a15.782 15.782 0 1 1 15.782-15.782 15.782 15.782 0 0 1-15.782 15.782zm142.53-43.099v-100.91a45.422 45.422 0 0 0-45.373-45.373h-17.261v-26.667l-43.331 42.448 43.33 42.449v-26.667h17.262a13.81 13.81 0 0 1 13.81 13.81v100.91a31.564 31.564 0 1 0 31.563 0zm-15.782 43.1a15.782 15.782 0 1 1 15.782-15.783 15.782 15.782 0 0 1-15.782 15.782z"/></svg>
 | 
				
			||||||
| 
		 After Width: | Height: | Size: 1.7 KiB  | 
							
								
								
									
										1
									
								
								static/img/homepage/platforms.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					<svg xmlns="http://www.w3.org/2000/svg" width="1000" height="1000" viewBox="150 150 650 650"><g fill="#eab167"><path stroke="#eab167" stroke-opacity=".894" stroke-width="2.126" d="M655.366 295.917h102.8v193.768h-102.8z" fill="#eab167000"/><rect width="376.029" height="274.791" x="225.888" y="362.06" stroke="#4d4d4d" stroke-linejoin="round" stroke-width="28.925" rx="29.052" fill="#eab167000"/><path stroke="#4d4d4d" stroke-linecap="round" stroke-miterlimit="10" stroke-width="28.925" d="M196.963 651.313h433.88" fill="#eab167000"/></g><path fill="#4d4d4d" stroke="#eab167" stroke-width=".417" d="M759.782 284.433H654.649a7.51 7.51 0 0 0-7.509 7.51v198.583a7.51 7.51 0 0 0 7.51 7.51h105.132a7.51 7.51 0 0 0 7.51-7.51V291.942a7.51 7.51 0 0 0-7.51-7.509zm-97.623 186.902V311.133h90.113v160.202z"/><path fill="#eab167" fill-rule="evenodd" d="m712.75 387.104-8.818 12.933-2.577-1.758 10.105-14.818a1.56 1.56 0 0 1 2.575-.003l10.128 14.796-2.573 1.762zm-19.815 12.949 10.788-15.82-2.667-1.818-10.788 15.82zM443.42 477.429l-47.027 68.965-13.741-9.37 53.884-79.021a8.315 8.315 0 0 1 13.732-.013l54.008 78.897-13.724 9.395zm-105.67 69.054 57.526-84.359-14.22-9.697-57.527 84.359z" clip-rule="evenodd"/></svg>
 | 
				
			||||||
| 
		 After Width: | Height: | Size: 1.2 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								static/img/insufficient-space.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 9.1 KiB  | 
							
								
								
									
										1
									
								
								static/img/logo-outline.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M8,15A2,2 0 0,1 6,13A2,2 0 0,1 8,11A2,2 0 0,1 10,13A2,2 0 0,1 8,15M10.5,17L12,14L13.5,17H10.5M16,15A2,2 0 0,1 14,13A2,2 0 0,1 16,11A2,2 0 0,1 18,13A2,2 0 0,1 16,15M22,11A10,10 0 0,0 12,1A10,10 0 0,0 2,11C2,13.8 3.2,16.3 5,18.1V22H19V18.1C20.8,16.3 22,13.8 22,11M17,20H15V18H13V20H11V18H9V20H7V17.2C5.2,15.7 4,13.5 4,11A8,8 0 0,1 12,3A8,8 0 0,1 20,11C20,13.5 18.8,15.8 17,17.2V20Z" /></svg>
 | 
				
			||||||
| 
		 After Width: | Height: | Size: 458 B  | 
							
								
								
									
										1
									
								
								static/img/logo-scan-outline.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M2 0C.9 0 0 .9 0 2V6H2V2H6V0H2M18 0V2H22V6H24V2C24 .9 23.1 0 22 0H18M9.5 13C8.7 13 8 12.3 8 11.5S8.7 10 9.5 10 11 10.7 11 11.5 10.3 13 9.5 13M11 15L12 13L13 15H11M14.5 13C13.7 13 13 12.3 13 11.5S13.7 10 14.5 10 16 10.7 16 11.5 15.3 13 14.5 13M0 18V22C0 23.1 .9 24 2 24H6V22H2V18H0M22 18V22H18V24H22C23.1 24 24 23.1 24 22V18H22M12 3C7.6 3 4 6.6 4 11C4 13 4.8 14.9 6 16.3V21H18V16.3C19.2 14.9 20 13.1 20 11C20 6.6 16.4 3 12 3M16 15.4V19H14V17H13V19H11V17H10V19H8V15.4C6.8 14.3 6 12.7 6 11C6 7.7 8.7 5 12 5S18 7.7 18 11C18 12.8 17.2 14.3 16 15.4Z" /></svg>
 | 
				
			||||||
| 
		 After Width: | Height: | Size: 622 B  | 
							
								
								
									
										1
									
								
								static/img/logo-scan.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M2 0C.9 0 0 .9 0 2V6H2V2H6V0H2M18 0V2H22V6H24V2C24 .9 23.1 0 22 0H18M12 3C7.6 3 4 6.6 4 11C4 13.5 5.2 15.8 7 17.2V21H9V18H11V21H13V18H15V21H17V17.2C18.8 15.7 20 13.5 20 11C20 6.6 16.4 3 12 3M8 14C6.9 14 6 13.1 6 12S6.9 10 8 10 10 10.9 10 12 9.1 14 8 14M10.5 16L12 13L13.5 16H10.5M16 14C14.9 14 14 13.1 14 12S14.9 10 16 10 18 10.9 18 12 17.1 14 16 14M0 18V22C0 23.1 .9 24 2 24H6V22H2V18H0M22 18V22H18V24H22C23.1 24 24 23.1 24 22V18H22Z" /></svg>
 | 
				
			||||||
| 
		 After Width: | Height: | Size: 513 B  | 
							
								
								
									
										1
									
								
								static/img/logo-white.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12,2A9,9 0 0,0 3,11C3,14.03 4.53,16.82 7,18.47V22H9V19H11V22H13V19H15V22H17V18.46C19.47,16.81 21,14 21,11A9,9 0 0,0 12,2M8,11A2,2 0 0,1 10,13A2,2 0 0,1 8,15A2,2 0 0,1 6,13A2,2 0 0,1 8,11M16,11A2,2 0 0,1 18,13A2,2 0 0,1 16,15A2,2 0 0,1 14,13A2,2 0 0,1 16,11M12,14L13.5,17H10.5L12,14Z" fill="#ffffff"/></svg>
 | 
				
			||||||
| 
		 After Width: | Height: | Size: 376 B  | 
							
								
								
									
										1
									
								
								static/img/logo.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12,2A9,9 0 0,0 3,11C3,14.03 4.53,16.82 7,18.47V22H9V19H11V22H13V19H15V22H17V18.46C19.47,16.81 21,14 21,11A9,9 0 0,0 12,2M8,11A2,2 0 0,1 10,13A2,2 0 0,1 8,15A2,2 0 0,1 6,13A2,2 0 0,1 8,11M16,11A2,2 0 0,1 18,13A2,2 0 0,1 16,15A2,2 0 0,1 14,13A2,2 0 0,1 16,11M12,14L13.5,17H10.5L12,14Z" /></svg>
 | 
				
			||||||
| 
		 After Width: | Height: | Size: 362 B  | 
							
								
								
									
										1
									
								
								static/img/readme/comment-alt.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><style>@media (prefers-color-scheme:dark){path{fill:#fff}}</style><path d="M448 0H64C28.7 0 0 28.7 0 64v288c0 35.3 28.7 64 64 64h96v84c0 7.1 5.8 12 12 12 2.4 0 4.9-.7 7.1-2.4L304 416h144c35.3 0 64-28.7 64-64V64c0-35.3-28.7-64-64-64zm16 352c0 8.8-7.2 16-16 16H288l-12.8 9.6L208 428v-60H64c-8.8 0-16-7.2-16-16V64c0-8.8 7.2-16 16-16h384c8.8 0 16 7.2 16 16v288z"/></svg>
 | 
				
			||||||
| 
		 After Width: | Height: | Size: 428 B  | 
							
								
								
									
										1
									
								
								static/img/readme/discord.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					<svg xmlns="http://www.w3.org/2000/svg" width="71" height="55" fill="#fff" viewBox="0 0 71 55"><g clip-path="url(#a)"><path d="M60.105 4.898A58.55 58.55 0 0 0 45.653.415a.22.22 0 0 0-.233.11 40.784 40.784 0 0 0-1.8 3.697c-5.456-.817-10.886-.817-16.23 0-.485-1.164-1.201-2.587-1.828-3.697a.228.228 0 0 0-.233-.11 58.386 58.386 0 0 0-14.451 4.483.207.207 0 0 0-.095.082C1.578 18.73-.944 32.144.293 45.39a.244.244 0 0 0 .093.167c6.073 4.46 11.955 7.167 17.729 8.962a.23.23 0 0 0 .249-.082 42.08 42.08 0 0 0 3.627-5.9.225.225 0 0 0-.123-.312 38.772 38.772 0 0 1-5.539-2.64.228.228 0 0 1-.022-.378 31.17 31.17 0 0 0 1.1-.862.22.22 0 0 1 .23-.03c11.619 5.304 24.198 5.304 35.68 0a.219.219 0 0 1 .233.027c.356.293.728.586 1.103.865a.228.228 0 0 1-.02.378 36.384 36.384 0 0 1-5.54 2.637.227.227 0 0 0-.121.315 47.249 47.249 0 0 0 3.624 5.897.225.225 0 0 0 .249.084c5.801-1.794 11.684-4.502 17.757-8.961a.228.228 0 0 0 .092-.164c1.48-15.315-2.48-28.618-10.497-40.412a.18.18 0 0 0-.093-.084Zm-36.38 32.427c-3.497 0-6.38-3.211-6.38-7.156 0-3.944 2.827-7.156 6.38-7.156 3.583 0 6.438 3.24 6.382 7.156 0 3.945-2.827 7.156-6.381 7.156Zm23.593 0c-3.498 0-6.38-3.211-6.38-7.156 0-3.944 2.826-7.156 6.38-7.156 3.582 0 6.437 3.24 6.38 7.156 0 3.945-2.798 7.156-6.38 7.156Z"/></g><defs><clipPath id="a"><path d="M0 0h71v55H0z"/></clipPath></defs></svg>
 | 
				
			||||||
| 
		 After Width: | Height: | Size: 1.3 KiB  |