Enable logging out by revoking the access token
This commit is contained in:
parent
856f215e36
commit
6d0bfa8fd7
|
@ -13,6 +13,7 @@ import {
|
||||||
import AsyncStorage from "@react-native-async-storage/async-storage";
|
import AsyncStorage from "@react-native-async-storage/async-storage";
|
||||||
|
|
||||||
import { withoutHTML } from "src/interface/rendering";
|
import { withoutHTML } from "src/interface/rendering";
|
||||||
|
import * as requests from "src/requests";
|
||||||
|
|
||||||
import { ScreenWithBackBarJsx } from "src/components/navigation/navigators";
|
import { ScreenWithBackBarJsx } from "src/components/navigation/navigators";
|
||||||
|
|
||||||
|
@ -46,184 +47,235 @@ const SettingsJsx = (props) => {
|
||||||
// Use Context to get this stuff eventually
|
// Use Context to get this stuff eventually
|
||||||
profile: TEST_PROFILE,
|
profile: TEST_PROFILE,
|
||||||
newProfile: TEST_PROFILE,
|
newProfile: TEST_PROFILE,
|
||||||
|
loaded: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
const fields = state.newProfile.fields;
|
const fields = state.newProfile.fields;
|
||||||
|
|
||||||
|
const _handleLogout = async () => {
|
||||||
|
await requests.postForm(
|
||||||
|
`https://${state.instance}/oauth/revoke`,
|
||||||
|
{
|
||||||
|
client_id: state.appObject.client_id,
|
||||||
|
client_secret: state.appObject.client_secret,
|
||||||
|
token: state.token.access_token,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
await AsyncStorage.multiRemove([
|
||||||
|
"@user_profile",
|
||||||
|
"@user_notifications",
|
||||||
|
"@user_instance",
|
||||||
|
"@user_token",
|
||||||
|
]);
|
||||||
|
|
||||||
|
props.navigation.navigate("Authenticate");
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
AsyncStorage
|
||||||
|
.multiGet([
|
||||||
|
"@user_profile",
|
||||||
|
"@user_instance",
|
||||||
|
"@user_token",
|
||||||
|
"@app_object",
|
||||||
|
])
|
||||||
|
.then(([profilePair, instancePair, tokenPair, appPair]) =>
|
||||||
|
[
|
||||||
|
JSON.parse(profilePair[1]),
|
||||||
|
instancePair[1],
|
||||||
|
JSON.parse(tokenPair[1]),
|
||||||
|
JSON.parse(appPair[1]),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
.then(([profile, instance, token, appObject]) => {
|
||||||
|
let newProfile = profile;
|
||||||
|
newProfile.fields = newProfile.fields == null
|
||||||
|
? []
|
||||||
|
: newProfile.fields;
|
||||||
|
|
||||||
|
setState({...state,
|
||||||
|
profile: profile,
|
||||||
|
newProfile: newProfile,
|
||||||
|
instance: instance,
|
||||||
|
appObject: appObject,
|
||||||
|
token: token,
|
||||||
|
loaded: true,
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ScreenWithBackBarJsx navigation = { props.navigation }>
|
<>
|
||||||
<View style = { styles.avatar.container }>
|
{ state.loaded
|
||||||
<Image
|
? <ScreenWithBackBarJsx navigation = { props.navigation }>
|
||||||
source = { { uri: state.profile.avatar } }
|
<View style = { styles.avatar.container }>
|
||||||
style = { styles.avatar.image }/>
|
<Image
|
||||||
<TouchableOpacity>
|
source = { { uri: state.profile.avatar } }
|
||||||
<Text style = { styles.avatar.change }>
|
style = { styles.avatar.image }/>
|
||||||
Change profile photo
|
<TouchableOpacity>
|
||||||
</Text>
|
<Text style = { styles.avatar.change }>
|
||||||
</TouchableOpacity>
|
Change profile photo
|
||||||
</View>
|
</Text>
|
||||||
<View style = { styles.input.container }>
|
</TouchableOpacity>
|
||||||
<Text style = { styles.label }>Display name</Text>
|
</View>
|
||||||
<TextInput
|
<View style = { styles.input.container }>
|
||||||
style = { styles.bar }
|
<Text style = { styles.label }>Display name</Text>
|
||||||
placeholder = { "Display name" }
|
<TextInput
|
||||||
value = { state.newProfile.display_name }
|
style = { styles.bar }
|
||||||
onChangeText = {
|
placeholder = { "Display name" }
|
||||||
(value) => {
|
value = { state.newProfile.display_name }
|
||||||
setState({...state,
|
onChangeText = {
|
||||||
newProfile: {...state.newProfile, display_name: value}
|
(value) => {
|
||||||
});
|
setState({...state,
|
||||||
}
|
newProfile: {...state.newProfile, display_name: value}
|
||||||
}/>
|
});
|
||||||
|
}
|
||||||
|
}/>
|
||||||
|
|
||||||
<Text style = { styles.label }>User name</Text>
|
<Text style = { styles.label }>User name</Text>
|
||||||
<TextInput
|
<TextInput
|
||||||
style = { styles.bar }
|
style = { styles.bar }
|
||||||
placeholder = { "User name" }
|
placeholder = { "User name" }
|
||||||
value = { state.newProfile.username }
|
value = { state.newProfile.username }
|
||||||
onChangeText = {
|
onChangeText = {
|
||||||
(value) => {
|
(value) => {
|
||||||
setState({...state,
|
setState({...state,
|
||||||
newProfile: {...state.newProfile, username: value}
|
newProfile: {...state.newProfile, username: value}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}/>
|
}/>
|
||||||
|
|
||||||
<Text style = { styles.label }>Bio</Text>
|
<Text style = { styles.label }>Bio</Text>
|
||||||
<TextInput
|
<TextInput
|
||||||
style = {
|
style = {
|
||||||
[
|
[
|
||||||
styles.bar,
|
styles.bar,
|
||||||
{ height: 100 },
|
{ height: 100 },
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
multiline = { true }
|
multiline = { true }
|
||||||
placeholder = { "Bio" }
|
placeholder = { "Bio" }
|
||||||
value = { withoutHTML(state.newProfile.note) }
|
value = { withoutHTML(state.newProfile.note) }
|
||||||
onChangeText = {
|
onChangeText = {
|
||||||
(value) => {
|
(value) => {
|
||||||
setState({...state,
|
setState({...state,
|
||||||
newProfile: {...state.newProfile, note: value}
|
newProfile: {...state.newProfile, note: value}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}/>
|
}/>
|
||||||
{
|
{
|
||||||
fields.map((field, i) =>
|
fields.map((field, i) =>
|
||||||
<View
|
<View
|
||||||
style = { styles.fields.container }
|
style = { styles.fields.container }
|
||||||
key = { i }>
|
key = { i }>
|
||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
onPress = {
|
onPress = {
|
||||||
() => {
|
() => {
|
||||||
let newFields;
|
let newFields;
|
||||||
if (fields.length == 1) {
|
if (fields.length == 1) {
|
||||||
newFields = [{ name: "", value: "" }];
|
newFields = [{ name: "", value: "" }];
|
||||||
} else {
|
} else {
|
||||||
newFields = state.newProfile.fields;
|
newFields = state.newProfile.fields;
|
||||||
newFields.splice(i, 1);
|
newFields.splice(i, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
setState({...state,
|
setState({...state,
|
||||||
newProfile: {...state.newProfile,
|
newProfile: {...state.newProfile,
|
||||||
fields: newFields,
|
fields: newFields,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}>
|
||||||
|
<Image
|
||||||
|
style = {
|
||||||
|
[
|
||||||
|
styles.fields.cross,
|
||||||
|
fields.length == 1
|
||||||
|
&& fields[0].name == ""
|
||||||
|
&& fields[0].value == ""
|
||||||
|
? { visibility: "hidden" }
|
||||||
|
: {}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
source = { require("assets/eva-icons/close.png") }/>
|
||||||
|
</TouchableOpacity>
|
||||||
|
<View style = { styles.fields.subContainer }>
|
||||||
|
<Text style = { styles.label }>Name</Text>
|
||||||
|
<TextInput
|
||||||
|
style = { [styles.bar, styles.fields.cell] }
|
||||||
|
placeholder = { "Name" }
|
||||||
|
value = { withoutHTML(fields[i].name) }
|
||||||
|
onChangeText = {
|
||||||
|
(text) => {
|
||||||
|
let newFields = fields;
|
||||||
|
newFields[i] = {...newFields[i],
|
||||||
|
name: text,
|
||||||
|
};
|
||||||
|
|
||||||
|
setState({...state,
|
||||||
|
newProfile: {...state.newProfile,
|
||||||
|
fields: newFields,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} />
|
||||||
|
</View>
|
||||||
|
<View style = { styles.fields.subContainer }>
|
||||||
|
<Text style = { styles.label }>Value</Text>
|
||||||
|
<TextInput
|
||||||
|
style = { [styles.bar, styles.fields.cell] }
|
||||||
|
placeholder = { "Value" }
|
||||||
|
value = { withoutHTML(fields[i].value) }
|
||||||
|
onChangeText = {
|
||||||
|
(text) => {
|
||||||
|
let newFields = fields;
|
||||||
|
newFields[i] = {...newFields[i],
|
||||||
|
value: text,
|
||||||
|
};
|
||||||
|
|
||||||
|
setState({...state,
|
||||||
|
newProfile: {...state.newProfile,
|
||||||
|
fields: newFields,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} />
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
<TouchableOpacity
|
||||||
|
onPress = {
|
||||||
|
() => {
|
||||||
|
setState({...state,
|
||||||
|
newProfile: {...state.newProfile,
|
||||||
|
fields: state.newProfile.fields.concat({ name: "", value: ""}),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}>
|
||||||
|
<Image
|
||||||
|
style = { styles.fields.plus }
|
||||||
|
source = { require("assets/eva-icons/plus.png") } />
|
||||||
|
</TouchableOpacity>
|
||||||
|
<TouchableOpacity style = { styles.button.container }>
|
||||||
|
<Text style = { styles.button.text }> Save Profile </Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
<TouchableOpacity
|
||||||
|
style = { styles.button.container }
|
||||||
|
onPress = { _handleLogout }>
|
||||||
|
<Text style = {
|
||||||
|
[ styles.button.text, styles.button.warning ]
|
||||||
}>
|
}>
|
||||||
<Image
|
Log out
|
||||||
style = {
|
</Text>
|
||||||
[
|
</TouchableOpacity>
|
||||||
styles.fields.cross,
|
</View>
|
||||||
fields.length == 1
|
</ScreenWithBackBarJsx>
|
||||||
&& fields[0].name == ""
|
: <></>
|
||||||
&& fields[0].value == ""
|
}
|
||||||
? { visibility: "hidden" }
|
</>
|
||||||
: {}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
source = { require("assets/eva-icons/close.png") }/>
|
|
||||||
</TouchableOpacity>
|
|
||||||
<View style = { styles.fields.subContainer }>
|
|
||||||
<Text style = { styles.label }>Name</Text>
|
|
||||||
<TextInput
|
|
||||||
style = { [styles.bar, styles.fields.cell] }
|
|
||||||
placeholder = { "Name" }
|
|
||||||
value = { withoutHTML(fields[i].name) }
|
|
||||||
onChangeText = {
|
|
||||||
(text) => {
|
|
||||||
let newFields = fields;
|
|
||||||
newFields[i] = {...newFields[i],
|
|
||||||
name: text,
|
|
||||||
};
|
|
||||||
|
|
||||||
setState({...state,
|
|
||||||
newProfile: {...state.newProfile,
|
|
||||||
fields: newFields,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} />
|
|
||||||
</View>
|
|
||||||
<View style = { styles.fields.subContainer }>
|
|
||||||
<Text style = { styles.label }>Value</Text>
|
|
||||||
<TextInput
|
|
||||||
style = { [styles.bar, styles.fields.cell] }
|
|
||||||
placeholder = { "Value" }
|
|
||||||
value = { withoutHTML(fields[i].value) }
|
|
||||||
onChangeText = {
|
|
||||||
(text) => {
|
|
||||||
let newFields = fields;
|
|
||||||
newFields[i] = {...newFields[i],
|
|
||||||
value: text,
|
|
||||||
};
|
|
||||||
|
|
||||||
setState({...state,
|
|
||||||
newProfile: {...state.newProfile,
|
|
||||||
fields: newFields,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} />
|
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
<TouchableOpacity
|
|
||||||
onPress = {
|
|
||||||
() => {
|
|
||||||
setState({...state,
|
|
||||||
newProfile: {...state.newProfile,
|
|
||||||
fields: state.newProfile.fields.concat({ name: "", value: ""}),
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}>
|
|
||||||
<Image
|
|
||||||
style = { styles.fields.plus }
|
|
||||||
source = { require("assets/eva-icons/plus.png") } />
|
|
||||||
</TouchableOpacity>
|
|
||||||
<TouchableOpacity style = { styles.button.container }>
|
|
||||||
<Text style = { styles.button.text }> Save Profile </Text>
|
|
||||||
</TouchableOpacity>
|
|
||||||
<TouchableOpacity
|
|
||||||
style = { styles.button.container }
|
|
||||||
onPress = {
|
|
||||||
() => {
|
|
||||||
AsyncStorage.multiRemove(
|
|
||||||
["@user_profile", "@user_notifications"]
|
|
||||||
).then(() => {
|
|
||||||
props.navigation.navigate("Authenticate");
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}>
|
|
||||||
<Text style = {
|
|
||||||
[ styles.button.text, styles.button.warning ]
|
|
||||||
}>
|
|
||||||
Log out
|
|
||||||
</Text>
|
|
||||||
</TouchableOpacity>
|
|
||||||
</View>
|
|
||||||
</ScreenWithBackBarJsx>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue