Skip to content
Snippets Groups Projects
Commit f9b9c81e authored by Flam3rboy's avatar Flam3rboy
Browse files

:art: login + register screen

parent ef469c4d
No related branches found
No related tags found
No related merge requests found
Showing
with 290 additions and 111 deletions
......@@ -459,9 +459,9 @@
ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = YES;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = fosscord/fosscord.entitlements;
CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_IDENTITY = "Apple Development";
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
CODE_SIGN_STYLE = Manual;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = 6L9MV38TFR;
ENABLE_BITCODE = NO;
......@@ -478,7 +478,7 @@
);
PRODUCT_BUNDLE_IDENTIFIER = com.fosscord.client;
PRODUCT_NAME = fosscord;
PROVISIONING_PROFILE_SPECIFIER = Fosscord;
PROVISIONING_PROFILE_SPECIFIER = "";
"PROVISIONING_PROFILE_SPECIFIER[sdk=macosx*]" = "";
SUPPORTS_MACCATALYST = YES;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
......@@ -496,11 +496,11 @@
ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = YES;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = fosscord/fosscord.entitlements;
CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_IDENTITY = "Apple Development";
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
CODE_SIGN_STYLE = Manual;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = "";
DEVELOPMENT_TEAM = 6L9MV38TFR;
INFOPLIST_FILE = fosscord/Info.plist;
"IPHONEOS_DEPLOYMENT_TARGET[sdk=macosx*]" = 14.2;
LD_RUNPATH_SEARCH_PATHS = (
......@@ -514,7 +514,7 @@
);
PRODUCT_BUNDLE_IDENTIFIER = com.fosscord.client;
PRODUCT_NAME = fosscord;
PROVISIONING_PROFILE_SPECIFIER = Fosscord;
PROVISIONING_PROFILE_SPECIFIER = "";
"PROVISIONING_PROFILE_SPECIFIER[sdk=macosx*]" = "";
SUPPORTS_MACCATALYST = YES;
SWIFT_VERSION = 5.0;
......
......@@ -42,8 +42,8 @@
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
selectedDebuggerIdentifier = ""
selectedLauncherIdentifier = "Xcode.IDEFoundation.Launcher.PosixSpawn"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
......
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>SchemeUserState</key>
<dict>
<key>fosscord.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>12</integer>
</dict>
</dict>
<key>SuppressBuildableAutocreation</key>
<dict>
<key>00E356ED1AD99517003FC87E</key>
<dict>
<key>primary</key>
<true/>
</dict>
<key>13B07F861A680F5B00A75B9A</key>
<dict>
<key>primary</key>
<true/>
</dict>
</dict>
</dict>
</plist>
No preview for this file type
......@@ -22,6 +22,8 @@
<string>????</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>CodePushDeploymentKey</key>
<string>opEbqvhRggsHT8ejgpyK2bsFB5V4IvHaODkYQ</string>
<key>LSApplicationCategoryType</key>
<string>public.app-category.social-networking</string>
<key>LSRequiresIPhoneOS</key>
......@@ -48,12 +50,8 @@
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
<key>CodePushDeploymentKey</key>
<string>opEbqvhRggsHT8ejgpyK2bsFB5V4IvHaODkYQ</string>
</dict>
</plist>
No preview for this file type
......@@ -37,8 +37,7 @@ body,
height: 100%;
}
.h-100,
.register {
.h-100 {
width: auto !important;
height: auto !important;
}
......
import React, { ReactElement, Suspense } from "react";
import React, { ReactElement, Suspense, useEffect } from "react";
import { Router, Route } from "./components/Router";
import { SafeAreaProvider } from "react-native-safe-area-context";
import { ErrorBoundary } from "./components/ErrorBoundary";
import { Provider } from "react-redux";
import Store from "./util/Store";
import { Themes } from "./util/Themes";
import { Platform, View } from "react-native";
import { Keyboard, KeyboardAvoidingView, Platform, View } from "react-native";
import BackHandler from "./components/BackHandler";
import { LogBox } from "react-native";
import Routes from "./components/Routes";
......@@ -25,10 +25,10 @@ Platform.isMobile = Platform.OS === "ios" || Platform.OS === "android";
export default function App() {
return (
<Provider store={Store}>
<ErrorBoundary>
<Router>
<Themes>
<SafeAreaProvider>
<SafeAreaProvider>
<Themes>
<ErrorBoundary>
<Router>
<View style={{ width: "100%", height: "100%" }} className="bg">
<Suspense fallback={<></>}>
<BackHandler>
......@@ -36,10 +36,10 @@ export default function App() {
</BackHandler>
</Suspense>
</View>
</SafeAreaProvider>
</Themes>
</Router>
</ErrorBoundary>
</Router>
</ErrorBoundary>
</Themes>
</SafeAreaProvider>
</Provider>
);
}
import React from "react";
import { Text, View, ViewProps } from "react-native";
import { Platform, Text, View, ViewProps } from "react-native";
import Svg, { Path, SvgProps } from "react-native-svg";
import Image from "../../../components/Image";
import FosscordLogo from "./icon.svg";
export default function Logo(props: ViewProps & { fontSize?: number; width?: number; color?: string; style?: any }) {
return (
......@@ -17,14 +19,18 @@ export default function Logo(props: ViewProps & { fontSize?: number; width?: num
width: undefined,
}}
>
<Svg width={props.width || 50} height={props.width || 50} viewBox="0 0 1778.84 1778.84">
<Path
fill={props.color || "#ff5f00"}
d="M3235.06,1765.51H1748V3544.35A1785,1785,0,0,0,2112.26,3507c690.15-143.63,1233.56-687,1377.19-1377.19a1785,1785,0,0,0,37.36-364.29ZM2112.26,3173.15V2830.41q13.6-7.22,27-14.65a1783.11,1783.11,0,0,0,458.54-364.29H2112.26V2129.8H3142.83C2965.64,2608.58,2588.25,2990.23,2112.26,3173.15Z"
transform="translate(-1747.97 -1765.51)"
/>
</Svg>
<Text style={{ fontSize: props.fontSize || 40, marginLeft: 30 }}>Fosscord</Text>
{Platform.OS === "windows" ? (
<Image style={{ width: props.width || 50, height: props.width || 50 }} source={FosscordLogo} />
) : (
<Svg width={props.width || 50} height={props.width || 50} viewBox="0 0 1778.84 1778.84">
<Path
fill={props.color || "#ff5f00"}
d="M3235.06,1765.51H1748V3544.35A1785,1785,0,0,0,2112.26,3507c690.15-143.63,1233.56-687,1377.19-1377.19a1785,1785,0,0,0,37.36-364.29ZM2112.26,3173.15V2830.41q13.6-7.22,27-14.65a1783.11,1783.11,0,0,0,458.54-364.29H2112.26V2129.8H3142.83C2965.64,2608.58,2588.25,2990.23,2112.26,3173.15Z"
transform="translate(-1747.97 -1765.51)"
/>
</Svg>
)}
<Text style={{ fontSize: props.fontSize || 50, marginLeft: 30 }}>Fosscord</Text>
</View>
);
}
<svg id="Ebene_1" data-name="Ebene 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1778.84 1778.84">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1778.84 1778.84">
<title>Fosscord Logo - SVG</title>
<path fill="blue" class="cls-1" d="M3235.06,1765.51H1748V3544.35A1785,1785,0,0,0,2112.26,3507c690.15-143.63,1233.56-687,1377.19-1377.19a1785,1785,0,0,0,37.36-364.29ZM2112.26,3173.15V2830.41q13.6-7.22,27-14.65a1783.11,1783.11,0,0,0,458.54-364.29H2112.26V2129.8H3142.83C2965.64,2608.58,2588.25,2990.23,2112.26,3173.15Z" transform="translate(-1747.97 -1765.51)" />
<path fill="white" d="M3235.06,1765.51H1748V3544.35A1785,1785,0,0,0,2112.26,3507c690.15-143.63,1233.56-687,1377.19-1377.19a1785,1785,0,0,0,37.36-364.29ZM2112.26,3173.15V2830.41q13.6-7.22,27-14.65a1783.11,1783.11,0,0,0,458.54-364.29H2112.26V2129.8H3142.83C2965.64,2608.58,2588.25,2990.23,2112.26,3173.15Z" transform="translate(-1747.97 -1765.51)" />
</svg>
\ No newline at end of file
......@@ -12,9 +12,6 @@
--text: #ffffff;
--text-accent: #b3b3b3; } }
.view {
background-color: var(--background); }
.text, .heading {
color: var(--text);
font-family: Arial;
......@@ -59,12 +56,20 @@
align-items: stretch;
text-align: left; }
.muted {
color: var(--text-accent);
font-size: 15px;
font-weight: 300; }
.bg, .introduction.welcome {
background-color: var(--background); }
.bg-primary, .button, .link {
background-color: var(--primary); }
.primary {
color: var(--primary); }
.text-accent {
color: var(--text-accent); }
......@@ -88,6 +93,15 @@
.introduction.welcome .waves {
display: none; } }
.introduction.features .text, .introduction.features .heading {
text-align: center; }
.introduction.features .title {
padding-bottom: 20px; }
.introduction.features .subtitle {
padding-bottom: 20px; }
.introduction.features .list {
max-width: 500px;
margin: 0 auto;
......@@ -101,14 +115,21 @@
.introduction.features .list .feature .tooltip {
padding: 10px;
font-size: 15px;
width: 100%;
background-color: var(--background-accent);
border-radius: 10px;
min-height: 100%;
background-color: var(--background); }
display: flex;
justify-content: center;
align-items: center;
text-align: center; }
.introduction.features .list .feature .wrapper {
box-shadow: 2px 2px 8px #000000ad;
background: var(--background-accent);
width: 100%;
border-radius: 5px; }
.introduction.features .list .feature .wrapper * {
text-align: center; }
border-radius: 5px;
display: flex;
justify-content: center;
align-items: center; }
.introduction.features .list .feature .wrapper .image {
margin-bottom: 10px;
padding: 10px;
......@@ -118,6 +139,34 @@
padding: 10px;
padding-top: 0; }
.page.login,
.page.register {
height: 100%;
width: 100%;
max-width: 460px;
margin: 0 auto;
padding: 0 15px;
display: flex; }
.page.login .entry,
.page.register .entry {
padding: 10px 0; }
.page.login .forgot-password,
.page.register .forgot-password {
margin-bottom: 10px; }
.page.login .submit,
.page.register .submit {
flex-grow: 1;
display: flex;
justify-content: flex-end; }
@media (min-width: 576px) {
.page.login .submit,
.page.register .submit {
flex-grow: 0; } }
.page.login .submit .button, .page.login .submit .link,
.page.register .submit .button,
.page.register .submit .link {
margin: 0; }
.elevated, .button.big, .big.link {
box-shadow: 0px 0px 5px #00000050; }
......@@ -201,12 +250,25 @@
max-width: 1320px; } }
.input {
height: 30px;
min-height: 30px;
width: 100%;
background: var(--background);
margin: 5px 0;
color: var(--text);
outline: none;
border: none; }
border: none;
background: var(--background-accent);
padding: 10px;
border-radius: 5px; }
.input:focus-visible {
outline-offset: 0; }
*:focus-visible {
outline: solid var(--primary) 2px;
border-radius: 5px;
outline-offset: 2px; }
.register-view {
margin: 10px; }
.label {
margin-bottom: 5px;
color: var(--text-accent);
text-transform: uppercase;
font-size: 13px;
font-weight: 900; }
......@@ -15,10 +15,6 @@
}
}
.view {
background-color: var(--background);
}
.text {
color: var(--text);
font-family: Arial;
......@@ -77,6 +73,12 @@
text-align: left;
}
.muted {
color: var(--text-accent);
font-size: 15px;
font-weight: 300;
}
.bg {
background-color: var(--background);
}
......@@ -85,6 +87,10 @@
background-color: var(--primary);
}
.primary {
color: var(--primary);
}
.text-accent {
color: var(--text-accent);
}
......@@ -120,6 +126,15 @@
}
.introduction.features {
.text {
text-align: center;
}
.title {
padding-bottom: 20px;
}
.subtitle {
padding-bottom: 20px;
}
.list {
max-width: 500px;
margin: 0 auto;
......@@ -136,18 +151,24 @@
.tooltip {
padding: 10px;
font-size: 15px;
width: 100%;
background-color: var(--background-accent);
border-radius: 10px;
min-height: 100%;
background-color: var(--background);
display: flex;
justify-content: center;
align-items: center;
text-align: center;
}
.wrapper {
box-shadow: 2px 2px 8px #000000ad;
background: var(--background-accent);
// box-shadow: 2px 2px 8px #000000ad;
width: 100%;
border-radius: 5px;
* {
text-align: center;
}
display: flex;
justify-content: center;
align-items: center;
.image {
margin-bottom: 10px;
......@@ -165,6 +186,38 @@
}
}
.page.login,
.page.register {
height: 100%;
width: 100%;
max-width: 460px;
margin: 0 auto;
padding: 0 15px;
display: flex;
.entry {
padding: 10px 0;
}
.forgot-password {
margin-bottom: 10px;
}
.submit {
flex-grow: 1;
display: flex;
justify-content: flex-end;
@media (min-width: 576px) {
flex-grow: 0;
}
.button {
margin: 0;
}
}
}
.elevated {
box-shadow: 0px 0px 5px #00000050;
}
......@@ -280,14 +333,30 @@
}
.input {
height: 30px;
min-height: 30px;
width: 100%;
background: var(--background);
margin: 5px 0;
color: var(--text);
outline: none;
border: none;
background: var(--background-accent);
padding: 10px;
border-radius: 5px;
&:focus-visible {
outline-offset: 0;
}
}
.register-view {
margin: 10px;
*:focus-visible {
outline: solid var(--primary) 2px;
border-radius: 5px;
outline-offset: 2px;
}
.label {
margin-bottom: 5px;
color: var(--text-accent);
text-transform: uppercase;
font-size: 13px;
font-weight: 900;
}
......@@ -10,6 +10,7 @@ let timeout: any;
export interface ButtonProps extends ViewProps {
onPress?: null | ((event: GestureResponderEvent) => void) | undefined;
hitSlop?: null | Insets | number | undefined;
loading?: boolean;
}
export default function Button(props: ButtonProps = {}) {
......@@ -19,6 +20,7 @@ export default function Button(props: ButtonProps = {}) {
return (
<Animated.View
className={"button-wrapper"}
style={{
transform: [{ scale: scaleAnim }, { translateX: offset }],
}}
......@@ -41,8 +43,6 @@ export default function Button(props: ButtonProps = {}) {
if (!isCanceled) props.onPress?.(event);
}}
isTVSelectable={true}
focusable={true}
accessible={true}
hitSlop={{ top: 10, bottom: 10, left: 10, right: 10 }}
onResponderStart={(event) => {
clearTimeout(timeout);
......@@ -94,8 +94,8 @@ export default function Button(props: ButtonProps = {}) {
}, 650);
}}
>
<View {...(props as any)} className={(props.className || "") + " button"}>
<Text className="text">{props.children}</Text>
<View accessible={true} focusable={true} {...(props as any)} className={(props.className || "") + " button"}>
<Text className="text">{props.loading ? "Loading ..." : props.children}</Text>
</View>
</Animated.View>
);
......
import React, { forwardRef, useRef } from "react";
import { Platform, TextInput as Input, TextInputProps, View } from "react-native";
export default forwardRef(function TextInput(props: TextInputProps, ref: any) {
if (Platform.OS === "web") return <Input className="input" ref={ref} {...props} />;
return (
<View className="input">
<Input
placeholderTextColor="grey"
hitSlop={{ bottom: 30, left: 30, right: 30, top: 30 }}
style={{ padding: 0 }}
ref={ref}
{...props}
/>
</View>
);
});
......@@ -10,7 +10,8 @@ export default function Tooltip(props: { children: ReactNode; tooltip: ReactNode
return (
<>
<View
{...props}
// {...props}
className={props.className}
style={{ overflow: "visible" }}
onStartShouldSetResponder={() => true}
onLayout={(e) => (layout.current = e.nativeEvent.layout)}
......@@ -22,6 +23,7 @@ export default function Tooltip(props: { children: ReactNode; tooltip: ReactNode
{props.children}
<Animated.View
className="tooltip"
onLayout={(e) => (tooltip.current = e.nativeEvent.layout)}
style={{
opacity,
......
......@@ -7,8 +7,9 @@ import Tooltip from "../../components/Tooltip";
export default function Features(props: any) {
return (
<SafeAreaView {...props} className="introduction features">
<ScrollView alwaysBounceVertical={false}>
<ScrollView alwaysBounceVertical={false} bounces={true}>
<Text className="title">Fosscord</Text>
<Text className="subtitle">Join the communication revolution</Text>
<View className="list">
<View className="feature">
......
......@@ -8,10 +8,7 @@ import Waves from "../../assets/images/Waves";
export default function Welcome(props: any) {
return (
<View {...props} className="introduction welcome">
<Logo width={80} color="white" />
<Text className="joinText" style={{ textAlign: "center", fontSize: 30, paddingTop: 50 }}>
Join the communication revolution
</Text>
<Logo width={70} color="white" />
</View>
);
}
......@@ -6,7 +6,7 @@ import Features from "./Features";
import Button from "../../components/Button";
import { SafeAreaView, useSafeAreaInsets } from "react-native-safe-area-context";
import { useNavigate } from "react-router";
import { useWindowDimensions, View } from "react-native";
import { Text, useWindowDimensions, View } from "react-native";
let page = 0;
......@@ -26,7 +26,7 @@ export default function Introduction() {
onScroll={(event) => (page = Math.round(event.nativeEvent.contentOffset.x / width))}
footer={({ next }: any) => (
<View style={{ paddingBottom: insets.bottom }}>
<Button onPress={() => (page >= 2 ? navigate("/") : next())}>Continue</Button>
<Button onPress={() => (page >= 1 ? navigate("/") : next())}>Continue</Button>
</View>
)}
>
......
import React, { useRef } from "react";
import { Image, Keyboard, StyleSheet, Text, View } from "react-native";
import { useMobile } from "../util/Styles";
import { Image, Keyboard, Pressable, ScrollView, StyleSheet, Text, View, TextInput as I } from "react-native";
import KeyboardAvoidingView from "../components/KeyboardAvoidingView";
import { useNavigate } from "react-router";
import { ScrollView, TextInput } from "react-native-gesture-handler";
import Button from "../components/Button";
import { SafeAreaView } from "react-native-safe-area-context";
import TextInput from "../components/TextInput";
const styles = StyleSheet.create({
formInputSection: {
......@@ -16,8 +14,6 @@ const styles = StyleSheet.create({
export default function Login() {
const navigate = useNavigate();
const isMobile = useMobile();
const emailElement = useRef<any>();
const passwordElement = useRef<any>();
......@@ -26,20 +22,18 @@ export default function Login() {
navigate("/login/instances/");
}
console.log("rerender login");
return (
<ScrollView className="login h-100">
<SafeAreaView>
<Image
source={{
uri: "https://github.com/fosscord/fosscord-client/blob/master/ios/fosscord/logo.png?raw=true",
}}
/>
<Text>Hey,{"\n"}Login now!</Text>
<Text>Explore Instances</Text>
<View>
<Text>
<Text>Email</Text>
</Text>
<ScrollView
keyboardShouldPersistTaps="always"
alwaysBounceVertical={false}
style={{ height: "100%", paddingHorizontal: 15, flex: 1, paddingBottom: 20 }}
>
<KeyboardAvoidingView scrollView safeArea behavior="padding" className="page login">
<Text className="title">Login</Text>
<View className="entry">
<Text className="label">Email</Text>
<TextInput
blurOnSubmit={false}
onSubmitEditing={() => {
......@@ -52,15 +46,19 @@ export default function Login() {
placeholder="Email"
/>
</View>
<View>
<Text>Password</Text>
<TextInput ref={passwordElement} textContentType="password" placeholder="Password" />
<View className="entry">
<Text className="label">Password</Text>
<TextInput ref={passwordElement} secureTextEntry textContentType="password" placeholder="Password" />
</View>
<Pressable onPress={() => navigate("/resetPassword")} className="forgot-password">
<Text className="muted">Reset password</Text>
</Pressable>
<View className="entry submit">
<Button onPress={() => navigate("/")}>
<Text>Login to fosscord.com</Text>
</Button>
</View>
<Text>Forgot your password? </Text>
<Button onPress={() => navigate("/")}>
<Text>Login to fosscord.com</Text>
</Button>
</SafeAreaView>
</KeyboardAvoidingView>
</ScrollView>
);
}
......@@ -9,14 +9,16 @@ export default function NotFound() {
const { data, error, isLoading } = useGetPokemonByNameQuery("bulbasaur");
return (
<SafeAreaView style={{ height: "100%" }}>
<Text className="title">Home</Text>
<SafeAreaView style={{ height: "100%", width: "100%", display: "flex", alignItems: "center", paddingHorizontal: 15 }}>
<View style={{ height: "100%", maxWidth: 360, width: "100%" }}>
<Text className="title">Home</Text>
<View>
<Link to="/introduction">Introduction</Link>
<Link to="/login">Login</Link>
<Link to="/register">Register</Link>
<Button>Test</Button>
<View>
<Link to="/introduction">Introduction</Link>
<Link to="/login">Login</Link>
<Link to="/register">Register</Link>
<Button>Test</Button>
</View>
</View>
</SafeAreaView>
);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment