diff --git a/src/components/pages/discover/search.js b/src/components/pages/discover/search.js
index 20810f3..f4c8766 100644
--- a/src/components/pages/discover/search.js
+++ b/src/components/pages/discover/search.js
@@ -1,96 +1,213 @@
-import React, { useState } from "react";
-import { View, TextInput, Text, Dimensions, Image } from "react-native";
+import React, { useState, useEffect } from "react";
+import {
+ View,
+ TextInput,
+ Text,
+ Dimensions,
+ Image,
+} from "react-native";
+import { TabView, TabBar, SceneMap } from "react-native-tab-view";
+import { FontAwesome } from '@expo/vector-icons';
+import AsyncStorage from "@react-native-async-storage/async-storage";
+import * as requests from "src/requests";
import { StatusBarSpace } from "src/interface/rendering";
import { ScreenWithTrayJsx } from "src/components/navigation/navigators";
-import { TouchableWithoutFeedback } from "react-native-gesture-handler";
-
-const TEST_IMAGE = "https://cache.desktopnexus.com/thumbseg/2255/2255124-bigthumbnail.jpg";
-const TEST_ACCOUNTS = [
- {
- id: 1,
- avatar: TEST_IMAGE,
- username: "njms",
- acct: "njms",
- display_name: "Nat🔆",
- },
- {
- id: 2,
- avatar: TEST_IMAGE,
- username: "njms",
- acct: "njms",
- display_name: "Nat🔆",
- }
-];
-
-const TEST_HASHTAGS = [
- {
- id: 1,
- name: "hashtag1",
- },
- {
- id: 2,
- name: "hashtag2",
- },
-];
+import { TouchableOpacity } from "react-native-gesture-handler";
function navCallbackFactory(navigation, route) {
return params => {
- console.log("test")
navigation.navigate(route, params);
}
}
const SearchJsx = ({navigation}) => {
+ // The number of additional items to fetch each time
+ const FETCH_LIMIT = 5;
+
let [state, setState] = useState({
query: "",
+ loaded: false,
+ accountOffset: 0,
+ hashtagOffset: 0,
});
- const accountCallback = navCallbackFactory(navigation, "ViewProfile");
- const hashtagCallback = navCallbackFactory(navigation, "ViewHashtag");
+ useEffect(() => {
+ let instance, accessToken;
+ AsyncStorage
+ .multiGet([
+ "@user_instance",
+ "@user_token",
+ ])
+ .then(([instancePair, tokenPair]) => {
+ instance = instancePair[1];
+ accessToken = JSON.parse(tokenPair[1]).access_token;
+
+ setState({...state,
+ instance,
+ accessToken,
+ loaded: true,
+ });
+ });
+ }, []);
+
+ const _handleSearch = async () => {
+ const results = await requests.fetchSearchResults(
+ state.instance,
+ state.accessToken,
+ {
+ q: state.query,
+ limit: FETCH_LIMIT,
+ }
+ );
+
+ setState({...state,
+ results,
+ accountOffset: FETCH_LIMIT,
+ hashtagOffset: FETCH_LIMIT,
+ });
+ };
+
+ const _handleShowMoreAccounts = async () => {
+ const { accounts } = await requests.fetchSearchResults(
+ state.instance,
+ state.accessToken,
+ {
+ q: state.query,
+ type: "accounts",
+ offset: state.accountOffset,
+ limit: FETCH_LIMIT,
+ }
+ );
+
+ setState({...state,
+ results: {...state.results,
+ accounts: state.results.accounts.concat(accounts),
+ },
+ accountOffset: state.accountOffset + FETCH_LIMIT,
+ });
+ };
+
+ const _handleShowMoreHashtags = async () => {
+ const { hashtags } = await requests.fetchSearchResults(
+ state.instance,
+ state.accessToken,
+ {
+ q: state.query,
+ type: "hashtags",
+ offset: state.hashtagOffset,
+ limit: FETCH_LIMIT,
+ }
+ );
+
+ setState({...state,
+ results: {...state.results,
+ hashtags: state.results.hashtags.concat(hashtags),
+ },
+ hashtagOffset: state.hashtagOffset + FETCH_LIMIT,
+ });
+ };
+
+ const [ index, setIndex ] = useState(0);
+ const [ routes ] = useState([
+ {
+ key: "accounts",
+ icon: "user",
+ },
+ {
+ key: "hashtags",
+ icon: "hashtag",
+ },
+ ]);
+
+ const AccountRenderer = () => (
+
+ );
+
+ const HashtagRenderer = () => (
+
+ );
+
+ const renderScene = SceneMap({
+ accounts: AccountRenderer,
+ hashtags: HashtagRenderer,
+ });
+
+ const renderTabBar = (props) => (
+
+ );
+
+ const renderIcon = ({ route, color }) => (
+
+ );
return (
-
-
-
- setState({query: q}) }
- onBlur = {
- () => {
- if (state.query == "") {
- navigation.navigate("Discover");
+ <>
+ { state.loaded
+ ?
+
+ setState({ ...state, query: q })
}
- }
+ onBlur = {
+ () => {
+ if (state.query == "") {
+ navigation.navigate("Discover");
+ }
+ }
+ }
+ value = { state.query } />
+
+
+
+
+ { state.results
+ ?
+ : <>>
}
- value = { state.query } />
-
- { state.query == "" ?
-
- :
- Accounts
-
- Hashtags
-
-
+
+ : <>>
}
-
+ >
);
};
const SearchItemJsx = (props) => {
return (
- props.callback(props.params) }>
+ props.callback(props.navParams) }>
{
{ props.children }
-
+
);
};
-const AccountsListJsx = (props) => {
+const AccountListJsx = (props) => {
return (
- {
- props.data.map(item => {
- return (
-
-
- { item.username }
-
-
- { item.display_name }
-
-
- );
- })
- }
+ <>
+ {
+ props.data.map(item => {
+ return (
+
+
+ { item.acct }
+
+
+ { item.display_name }
+
+
+ );
+ })
+ }
+ >
+ <>
+ { props.data.length == props.offset
+ ?
+
+
+ Show more?
+
+
+
+ : <>>
+ }
+ >
);
};
@@ -131,36 +263,58 @@ const AccountsListJsx = (props) => {
const HashtagListJsx = (props) => {
return (
- {
- props.data.map(item => {
- return (
-
-
- #{ item.name }
-
-
- );
- })
- }
+ <>
+ {
+ props.data.map((item, i) => {
+ return (
+
+
+ #{ item.name }
+
+
+ );
+ })
+ }
+ >
+ <>
+ { props.data.length == props.offset
+ ?
+
+
+ Show more?
+
+
+
+ :<>>
+ }
+ >
);
}
+const SCREEN_WIDTH = Dimensions.get("window").width;
const styles = {
form: {
- display: "flex",
- justifyContent: "center",
- backgroundColor: "white",
- padding: 20
- },
- searchBar: {
- padding: 10,
- fontSize: 17,
- color: "#888"
+ container: {
+ flexDirection: "row",
+ justifyContent: "center",
+ backgroundColor: "white",
+ padding: 20,
+ },
+ input: {
+ flexGrow: 1,
+ padding: 10,
+ fontSize: 17,
+ color: "#888"
+ },
+ submit: {
+ padding: 20,
+ }
},
label: {
padding: 10,
@@ -184,7 +338,25 @@ const styles = {
height: 50,
borderRadius: 25,
marginRight: 10,
- }
+ },
+ showMore: {
+ container: {
+ justifyContent: "center",
+ alignItems: "center"
+ },
+ button: {
+ borderWidth: 1,
+ borderColor: "#888",
+ borderRadius: 5,
+ padding: 10,
+ margin: 20
+ },
+ },
+
+ tabBar: {
+ indicator: { backgroundColor: "black" },
+ tab: { backgroundColor: "white" },
+ },
}
export default SearchJsx;
diff --git a/src/components/pages/profile.js b/src/components/pages/profile.js
index 70681e6..a915d6c 100644
--- a/src/components/pages/profile.js
+++ b/src/components/pages/profile.js
@@ -71,29 +71,22 @@ const ViewProfileJsx = ({navigation}) => {
.multiGet(["@user_profile", "@user_instance", "@user_token"])
.then(([ ownProfilePair, ownDomainPair, tokenPair ]) => {
ownProfile = JSON.parse(ownProfilePair[1]);
- ownDomain = ownDomainPair[1];
+ instance = ownDomainPair[1];
accessToken = JSON.parse(tokenPair[1]).access_token;
- const parsedAcct = state.profile.acct.split("@");
- domain = parsedAcct.length == 1
- ? ownDomain // There's no @ in the acct, thus it's a local user
- : parsedAcct [1] // The part of profile.acct after the @
-
return Promise.all([
requests.fetchFollowing(
- ownDomain,
+ instance,
ownProfile.id,
accessToken
),
requests.fetchFollowers(
- domain,
+ instance,
state.profile.id,
accessToken
),
requests.fetchAccountStatuses(
- // NOTE: Should be fetched from remote instance if
- // necessary Thus, we use domain and not ownDomain
- domain,
+ instance,
state.profile.id,
accessToken
)
diff --git a/src/requests.js b/src/requests.js
index c3b9bdd..e144110 100644
--- a/src/requests.js
+++ b/src/requests.js
@@ -55,7 +55,7 @@ export async function postForm(url, data, token = false) {
export async function get(url, token = false, data = false) {
let completeURL;
if (data) {
- let params = new URLSearchParams(data)
+ let params = new URLSearchParams(data);
completeURL = `${url}?${params.toString()}`;
} else {
completeURL = url;
@@ -113,3 +113,12 @@ export async function fetchPublicTimeline(domain, token, params = false) {
);
return resp.json();
}
+
+export async function fetchSearchResults(domain, token, params) {
+ const resp = await get(
+ `https://${domain}/api/v2/search`,
+ token,
+ params
+ );
+ return resp.json();
+}