diff --git a/404.html b/404.html index 74f7b2a5..f01d41a9 100644 --- a/404.html +++ b/404.html @@ -8,8 +8,8 @@ Page Not Found | Ignite Cookbook for React Native - - + +
@@ -36,7 +36,7 @@

Page Not Found

We could not find what you were looking for.

Please contact the owner of the site that linked you to the original URL and let them know their link is broken.

- - + + \ No newline at end of file diff --git a/assets/js/55960ee5.116e96b1.js b/assets/js/55960ee5.116e96b1.js deleted file mode 100644 index d74e51f1..00000000 --- a/assets/js/55960ee5.116e96b1.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkignite_cookbook=self.webpackChunkignite_cookbook||[]).push([[4121],{8070:e=>{e.exports=JSON.parse('[{"label":"Intro","permalink":"/docs/tags/intro","count":2},{"label":"Accessibility","permalink":"/docs/tags/accessibility","count":3},{"label":"Guide","permalink":"/docs/tags/guide","count":6},{"label":"CI/CD","permalink":"/docs/tags/ci-cd","count":2},{"label":"iOS","permalink":"/docs/tags/i-os","count":2},{"label":"Android","permalink":"/docs/tags/android","count":3},{"label":"Testing","permalink":"/docs/tags/testing","count":2},{"label":"Authentication","permalink":"/docs/tags/authentication","count":1},{"label":"Apisauce","permalink":"/docs/tags/apisauce","count":1},{"label":"Expo","permalink":"/docs/tags/expo","count":5},{"label":"expo-updates","permalink":"/docs/tags/expo-updates","count":1},{"label":"EAS Update","permalink":"/docs/tags/eas-update","count":1},{"label":"Environment Variables","permalink":"/docs/tags/environment-variables","count":1},{"label":"Generator","permalink":"/docs/tags/generator","count":1},{"label":"Maestro","permalink":"/docs/tags/maestro","count":1},{"label":"MMKV","permalink":"/docs/tags/mmkv","count":1},{"label":"AsyncStorage","permalink":"/docs/tags/async-storage","count":1},{"label":"Debug","permalink":"/docs/tags/debug","count":1},{"label":"VisionCamera","permalink":"/docs/tags/vision-camera","count":1},{"label":"react-native-vision-camera","permalink":"/docs/tags/react-native-vision-camera","count":1},{"label":"Redux","permalink":"/docs/tags/redux","count":1},{"label":"MobX","permalink":"/docs/tags/mob-x","count":1},{"label":"State Management","permalink":"/docs/tags/state-management","count":1},{"label":"TextField","permalink":"/docs/tags/text-field","count":1},{"label":"SelectField","permalink":"/docs/tags/select-field","count":1},{"label":"UI","permalink":"/docs/tags/ui","count":2},{"label":"expo-dev-client","permalink":"/docs/tags/expo-dev-client","count":1},{"label":"TypeScript","permalink":"/docs/tags/type-script","count":1},{"label":"Babel","permalink":"/docs/tags/babel","count":1},{"label":"FlatList","permalink":"/docs/tags/flat-list","count":1},{"label":"SectionList","permalink":"/docs/tags/section-list","count":1},{"label":"scrollTo","permalink":"/docs/tags/scroll-to","count":1},{"label":"Yarn","permalink":"/docs/tags/yarn","count":1},{"label":"Dependencies","permalink":"/docs/tags/dependencies","count":1}]')}}]); \ No newline at end of file diff --git a/assets/js/55960ee5.61d68dd9.js b/assets/js/55960ee5.61d68dd9.js new file mode 100644 index 00000000..c05af7e3 --- /dev/null +++ b/assets/js/55960ee5.61d68dd9.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkignite_cookbook=self.webpackChunkignite_cookbook||[]).push([[4121],{8070:e=>{e.exports=JSON.parse('[{"label":"Intro","permalink":"/docs/tags/intro","count":2},{"label":"Accessibility","permalink":"/docs/tags/accessibility","count":3},{"label":"Guide","permalink":"/docs/tags/guide","count":6},{"label":"CI/CD","permalink":"/docs/tags/ci-cd","count":2},{"label":"iOS","permalink":"/docs/tags/i-os","count":2},{"label":"Android","permalink":"/docs/tags/android","count":3},{"label":"Testing","permalink":"/docs/tags/testing","count":2},{"label":"Authentication","permalink":"/docs/tags/authentication","count":1},{"label":"Apisauce","permalink":"/docs/tags/apisauce","count":1},{"label":"Expo","permalink":"/docs/tags/expo","count":6},{"label":"expo-updates","permalink":"/docs/tags/expo-updates","count":1},{"label":"EAS Update","permalink":"/docs/tags/eas-update","count":1},{"label":"Environment Variables","permalink":"/docs/tags/environment-variables","count":1},{"label":"expo-router","permalink":"/docs/tags/expo-router","count":1},{"label":"react-navigation","permalink":"/docs/tags/react-navigation","count":1},{"label":"Generator","permalink":"/docs/tags/generator","count":1},{"label":"Maestro","permalink":"/docs/tags/maestro","count":1},{"label":"MMKV","permalink":"/docs/tags/mmkv","count":1},{"label":"AsyncStorage","permalink":"/docs/tags/async-storage","count":1},{"label":"Debug","permalink":"/docs/tags/debug","count":1},{"label":"VisionCamera","permalink":"/docs/tags/vision-camera","count":1},{"label":"react-native-vision-camera","permalink":"/docs/tags/react-native-vision-camera","count":1},{"label":"Redux","permalink":"/docs/tags/redux","count":1},{"label":"MobX","permalink":"/docs/tags/mob-x","count":1},{"label":"State Management","permalink":"/docs/tags/state-management","count":1},{"label":"TextField","permalink":"/docs/tags/text-field","count":1},{"label":"SelectField","permalink":"/docs/tags/select-field","count":1},{"label":"UI","permalink":"/docs/tags/ui","count":2},{"label":"expo-dev-client","permalink":"/docs/tags/expo-dev-client","count":1},{"label":"TypeScript","permalink":"/docs/tags/type-script","count":1},{"label":"Babel","permalink":"/docs/tags/babel","count":1},{"label":"FlatList","permalink":"/docs/tags/flat-list","count":1},{"label":"SectionList","permalink":"/docs/tags/section-list","count":1},{"label":"scrollTo","permalink":"/docs/tags/scroll-to","count":1},{"label":"Yarn","permalink":"/docs/tags/yarn","count":1},{"label":"Dependencies","permalink":"/docs/tags/dependencies","count":1}]')}}]); \ No newline at end of file diff --git a/assets/js/7b45617e.7f1eaea8.js b/assets/js/7b45617e.7f1eaea8.js new file mode 100644 index 00000000..25af362f --- /dev/null +++ b/assets/js/7b45617e.7f1eaea8.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkignite_cookbook=self.webpackChunkignite_cookbook||[]).push([[1833],{3905:(e,t,n)=>{n.d(t,{Zo:()=>c,kt:()=>d});var r=n(7294);function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function a(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function i(e){for(var t=1;t=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var s=r.createContext({}),l=function(e){var t=r.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},c=function(e){var t=l(e.components);return r.createElement(s.Provider,{value:t},e.children)},m={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},u=r.forwardRef((function(e,t){var n=e.components,o=e.mdxType,a=e.originalType,s=e.parentName,c=p(e,["components","mdxType","originalType","parentName"]),u=l(n),d=o,g=u["".concat(s,".").concat(d)]||u[d]||m[d]||a;return n?r.createElement(g,i(i({ref:t},c),{},{components:n})):r.createElement(g,i({ref:t},c))}));function d(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var a=n.length,i=new Array(a);i[0]=u;var p={};for(var s in t)hasOwnProperty.call(t,s)&&(p[s]=t[s]);p.originalType=e,p.mdxType="string"==typeof e?e:o,i[1]=p;for(var l=2;l{n.r(t),n.d(t,{assets:()=>s,contentTitle:()=>i,default:()=>m,frontMatter:()=>a,metadata:()=>p,toc:()=>l});var r=n(7462),o=(n(7294),n(3905));const a={title:"Generator for Component Tests",description:"Customize `npx ignite-cli generate component` to add test files for each component generated",tags:["Generator"],last_update:{author:"Joshua Yoes"},publish_date:new Date("2022-10-10T00:00:00.000Z")},i="Add component tests to `npx ignite-cli generate component`",p={unversionedId:"recipes/GeneratorComponentTests",id:"recipes/GeneratorComponentTests",title:"Generator for Component Tests",description:"Customize `npx ignite-cli generate component` to add test files for each component generated",source:"@site/docs/recipes/GeneratorComponentTests.md",sourceDirName:"recipes",slug:"/recipes/GeneratorComponentTests",permalink:"/docs/recipes/GeneratorComponentTests",draft:!1,tags:[{label:"Generator",permalink:"/docs/tags/generator"}],version:"current",lastUpdatedBy:"Joshua Yoes",lastUpdatedAt:1681985935,formattedLastUpdatedAt:"Apr 20, 2023",frontMatter:{title:"Generator for Component Tests",description:"Customize `npx ignite-cli generate component` to add test files for each component generated",tags:["Generator"],last_update:{author:"Joshua Yoes"},publish_date:"2022-10-10T00:00:00.000Z"},sidebar:"mainSidebar",previous:{title:"Expo Router",permalink:"/docs/recipes/ExpoRouter"},next:{title:"Maestro Setup",permalink:"/docs/recipes/MaestroSetup"}},s={},l=[{value:"Setup @testing-library/react-native",id:"setup-testing-libraryreact-native",level:2},{value:"Component Generators",id:"component-generators",level:2},{value:"Customizing Component Generators",id:"customizing-component-generators",level:2},{value:"Testing",id:"testing",level:2}],c={toc:l};function m(e){let{components:t,...n}=e;return(0,o.kt)("wrapper",(0,r.Z)({},c,n,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("h1",{id:"add-component-tests-to-npx-ignite-cli-generate-component"},"Add component tests to ",(0,o.kt)("inlineCode",{parentName:"h1"},"npx ignite-cli generate component")),(0,o.kt)("p",null,"Did you know that Ignite automatically generates files for you? And that you can customize those generators?"),(0,o.kt)("p",null,"Here is how to automatically generate components and tests for them using ",(0,o.kt)("inlineCode",{parentName:"p"},"@testing-library/react-native")),(0,o.kt)("h2",{id:"setup-testing-libraryreact-native"},"Setup ",(0,o.kt)("inlineCode",{parentName:"h2"},"@testing-library/react-native")),(0,o.kt)("p",null,"First, we will want to add ",(0,o.kt)("inlineCode",{parentName:"p"},"@testing-library/react-native")," to our Ignite project. ",(0,o.kt)("a",{parentName:"p",href:"https://reactnativetesting.io/component/setup"},"Josh Justice has an excellent setup guide to follow along at reactnativetesting.io")),(0,o.kt)("h2",{id:"component-generators"},"Component Generators"),(0,o.kt)("p",null,"There are a variety of generators, but today we are going to focus on ",(0,o.kt)("inlineCode",{parentName:"p"},"npx ignite-cli generate component")),(0,o.kt)("p",null,"Ignite will look in the ",(0,o.kt)("inlineCode",{parentName:"p"},"ignite/templates/*")," directory for what templates to run on each command."),(0,o.kt)("p",null,"By default, Ignite provides a ",(0,o.kt)("inlineCode",{parentName:"p"},"ignite/templates/component/NAME.tsx.ejs")," template for creating a component file."),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},"We use ejs and frontmatter to write our templates, you can read more about syntax ",(0,o.kt)("a",{parentName:"li",href:"https://github.com/infinitered/ignite/blob/master/docs/Generator-Templates.md"},"in the Ignite docs"),"."),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"NAME")," in ",(0,o.kt)("inlineCode",{parentName:"li"},"ignite/templates/component/NAME.tsx.ejs")," is replaced with the first argument passed to our generator. So ",(0,o.kt)("inlineCode",{parentName:"li"},"npx ignite-cli generate component Profile")," would create ",(0,o.kt)("inlineCode",{parentName:"li"},"app/components/Profile.tsx"))),(0,o.kt)("h2",{id:"customizing-component-generators"},"Customizing Component Generators"),(0,o.kt)("p",null,"Add the following file to ",(0,o.kt)("inlineCode",{parentName:"p"},"ignite/templates/component/NAME.spec.tsx.ejs")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-ejs"},'---\ndestinationDir: app/components/specs\n---\n// https://reactnativetesting.io/component/testing/\n\nimport React from "react"\nimport { fireEvent, render, screen } from "@testing-library/react-native"\nimport { <%= props.pascalCaseName %> } from "../<%= props.pascalCaseName %>"\n\ndescribe("<%= props.pascalCaseName %>", () => {\n it("renders", () => {\n render(<<%= props.pascalCaseName %> />)\n expect(screen.getByText("Hello")).toBeTruthy()\n })\n})\n')),(0,o.kt)("p",null,"Now, when we run ",(0,o.kt)("inlineCode",{parentName:"p"},"npx ignite-cli generate component Profile"),", it will create both ",(0,o.kt)("inlineCode",{parentName:"p"},"app/components/Profile.tsx")," ",(0,o.kt)("em",{parentName:"p"},"and")," ",(0,o.kt)("inlineCode",{parentName:"p"},"app/components/specs/Profile.spec.tsx")),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"ignite/templates/component/NAME.spec.tsx.ejs")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"ignite/templates/component/NAME.tsx.ejs"))),(0,o.kt)("h2",{id:"testing"},"Testing"),(0,o.kt)("p",null,"Now, all we need to do is run ",(0,o.kt)("inlineCode",{parentName:"p"},"yarn test"),"! If everything was set up properly, you should have a new suite of passing tests!"))}m.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/7b45617e.eee2553e.js b/assets/js/7b45617e.eee2553e.js deleted file mode 100644 index cda8696c..00000000 --- a/assets/js/7b45617e.eee2553e.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkignite_cookbook=self.webpackChunkignite_cookbook||[]).push([[1833],{3905:(e,t,n)=>{n.d(t,{Zo:()=>c,kt:()=>d});var r=n(7294);function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function a(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function i(e){for(var t=1;t=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var s=r.createContext({}),l=function(e){var t=r.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},c=function(e){var t=l(e.components);return r.createElement(s.Provider,{value:t},e.children)},m={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},u=r.forwardRef((function(e,t){var n=e.components,o=e.mdxType,a=e.originalType,s=e.parentName,c=p(e,["components","mdxType","originalType","parentName"]),u=l(n),d=o,g=u["".concat(s,".").concat(d)]||u[d]||m[d]||a;return n?r.createElement(g,i(i({ref:t},c),{},{components:n})):r.createElement(g,i({ref:t},c))}));function d(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var a=n.length,i=new Array(a);i[0]=u;var p={};for(var s in t)hasOwnProperty.call(t,s)&&(p[s]=t[s]);p.originalType=e,p.mdxType="string"==typeof e?e:o,i[1]=p;for(var l=2;l{n.r(t),n.d(t,{assets:()=>s,contentTitle:()=>i,default:()=>m,frontMatter:()=>a,metadata:()=>p,toc:()=>l});var r=n(7462),o=(n(7294),n(3905));const a={title:"Generator for Component Tests",description:"Customize `npx ignite-cli generate component` to add test files for each component generated",tags:["Generator"],last_update:{author:"Joshua Yoes"},publish_date:new Date("2022-10-10T00:00:00.000Z")},i="Add component tests to `npx ignite-cli generate component`",p={unversionedId:"recipes/GeneratorComponentTests",id:"recipes/GeneratorComponentTests",title:"Generator for Component Tests",description:"Customize `npx ignite-cli generate component` to add test files for each component generated",source:"@site/docs/recipes/GeneratorComponentTests.md",sourceDirName:"recipes",slug:"/recipes/GeneratorComponentTests",permalink:"/docs/recipes/GeneratorComponentTests",draft:!1,tags:[{label:"Generator",permalink:"/docs/tags/generator"}],version:"current",lastUpdatedBy:"Joshua Yoes",lastUpdatedAt:1681985935,formattedLastUpdatedAt:"Apr 20, 2023",frontMatter:{title:"Generator for Component Tests",description:"Customize `npx ignite-cli generate component` to add test files for each component generated",tags:["Generator"],last_update:{author:"Joshua Yoes"},publish_date:"2022-10-10T00:00:00.000Z"},sidebar:"mainSidebar",previous:{title:"Environment Variables",permalink:"/docs/recipes/EnvironmentVariables"},next:{title:"Maestro Setup",permalink:"/docs/recipes/MaestroSetup"}},s={},l=[{value:"Setup @testing-library/react-native",id:"setup-testing-libraryreact-native",level:2},{value:"Component Generators",id:"component-generators",level:2},{value:"Customizing Component Generators",id:"customizing-component-generators",level:2},{value:"Testing",id:"testing",level:2}],c={toc:l};function m(e){let{components:t,...n}=e;return(0,o.kt)("wrapper",(0,r.Z)({},c,n,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("h1",{id:"add-component-tests-to-npx-ignite-cli-generate-component"},"Add component tests to ",(0,o.kt)("inlineCode",{parentName:"h1"},"npx ignite-cli generate component")),(0,o.kt)("p",null,"Did you know that Ignite automatically generates files for you? And that you can customize those generators?"),(0,o.kt)("p",null,"Here is how to automatically generate components and tests for them using ",(0,o.kt)("inlineCode",{parentName:"p"},"@testing-library/react-native")),(0,o.kt)("h2",{id:"setup-testing-libraryreact-native"},"Setup ",(0,o.kt)("inlineCode",{parentName:"h2"},"@testing-library/react-native")),(0,o.kt)("p",null,"First, we will want to add ",(0,o.kt)("inlineCode",{parentName:"p"},"@testing-library/react-native")," to our Ignite project. ",(0,o.kt)("a",{parentName:"p",href:"https://reactnativetesting.io/component/setup"},"Josh Justice has an excellent setup guide to follow along at reactnativetesting.io")),(0,o.kt)("h2",{id:"component-generators"},"Component Generators"),(0,o.kt)("p",null,"There are a variety of generators, but today we are going to focus on ",(0,o.kt)("inlineCode",{parentName:"p"},"npx ignite-cli generate component")),(0,o.kt)("p",null,"Ignite will look in the ",(0,o.kt)("inlineCode",{parentName:"p"},"ignite/templates/*")," directory for what templates to run on each command."),(0,o.kt)("p",null,"By default, Ignite provides a ",(0,o.kt)("inlineCode",{parentName:"p"},"ignite/templates/component/NAME.tsx.ejs")," template for creating a component file."),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},"We use ejs and frontmatter to write our templates, you can read more about syntax ",(0,o.kt)("a",{parentName:"li",href:"https://github.com/infinitered/ignite/blob/master/docs/Generator-Templates.md"},"in the Ignite docs"),"."),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"NAME")," in ",(0,o.kt)("inlineCode",{parentName:"li"},"ignite/templates/component/NAME.tsx.ejs")," is replaced with the first argument passed to our generator. So ",(0,o.kt)("inlineCode",{parentName:"li"},"npx ignite-cli generate component Profile")," would create ",(0,o.kt)("inlineCode",{parentName:"li"},"app/components/Profile.tsx"))),(0,o.kt)("h2",{id:"customizing-component-generators"},"Customizing Component Generators"),(0,o.kt)("p",null,"Add the following file to ",(0,o.kt)("inlineCode",{parentName:"p"},"ignite/templates/component/NAME.spec.tsx.ejs")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-ejs"},'---\ndestinationDir: app/components/specs\n---\n// https://reactnativetesting.io/component/testing/\n\nimport React from "react"\nimport { fireEvent, render, screen } from "@testing-library/react-native"\nimport { <%= props.pascalCaseName %> } from "../<%= props.pascalCaseName %>"\n\ndescribe("<%= props.pascalCaseName %>", () => {\n it("renders", () => {\n render(<<%= props.pascalCaseName %> />)\n expect(screen.getByText("Hello")).toBeTruthy()\n })\n})\n')),(0,o.kt)("p",null,"Now, when we run ",(0,o.kt)("inlineCode",{parentName:"p"},"npx ignite-cli generate component Profile"),", it will create both ",(0,o.kt)("inlineCode",{parentName:"p"},"app/components/Profile.tsx")," ",(0,o.kt)("em",{parentName:"p"},"and")," ",(0,o.kt)("inlineCode",{parentName:"p"},"app/components/specs/Profile.spec.tsx")),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"ignite/templates/component/NAME.spec.tsx.ejs")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"ignite/templates/component/NAME.tsx.ejs"))),(0,o.kt)("h2",{id:"testing"},"Testing"),(0,o.kt)("p",null,"Now, all we need to do is run ",(0,o.kt)("inlineCode",{parentName:"p"},"yarn test"),"! If everything was set up properly, you should have a new suite of passing tests!"))}m.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/935f2afb.632193eb.js b/assets/js/935f2afb.632193eb.js deleted file mode 100644 index 66307fc6..00000000 --- a/assets/js/935f2afb.632193eb.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkignite_cookbook=self.webpackChunkignite_cookbook||[]).push([[53],{1109:e=>{e.exports=JSON.parse('{"pluginId":"default","version":"current","label":"Next","banner":null,"badge":false,"className":"docs-version-current","isLast":true,"docsSidebars":{"mainSidebar":[{"type":"link","label":"Intro to Recipes","href":"/docs/intro","docId":"intro"},{"type":"link","label":"Browse By Tag","href":"/docs/tags"},{"type":"category","label":"Recipes","collapsed":false,"items":[{"type":"link","label":"Accessiblity Font Sizes","href":"/docs/recipes/AccessibilityFontSizes","docId":"recipes/AccessibilityFontSizes"},{"type":"link","label":"CircleCI CD Setup - React Native","href":"/docs/recipes/CircleCIRNSetup","docId":"recipes/CircleCIRNSetup"},{"type":"link","label":"Creating a Good Experience for Screen Readers","href":"/docs/recipes/CreatingGreateExperienceForScreenReaders","docId":"recipes/CreatingGreateExperienceForScreenReaders"},{"type":"link","label":"Detox Intro","href":"/docs/recipes/DetoxIntro","docId":"recipes/DetoxIntro"},{"type":"link","label":"Distributing Auth Token to APIs","href":"/docs/recipes/DistributingAuthTokenToAPI","docId":"recipes/DistributingAuthTokenToAPI"},{"type":"link","label":"EAS Update","href":"/docs/recipes/EASUpdate","docId":"recipes/EASUpdate"},{"type":"link","label":"Environment Variables","href":"/docs/recipes/EnvironmentVariables","docId":"recipes/EnvironmentVariables"},{"type":"link","label":"Generator for Component Tests","href":"/docs/recipes/GeneratorComponentTests","docId":"recipes/GeneratorComponentTests"},{"type":"link","label":"Maestro Setup","href":"/docs/recipes/MaestroSetup","docId":"recipes/MaestroSetup"},{"type":"link","label":"Migrating to MMKV","href":"/docs/recipes/MigratingToMMKV","docId":"recipes/MigratingToMMKV"},{"type":"link","label":"Patching/Building Android .aar From Source","href":"/docs/recipes/PatchingBuildingAndroid","docId":"recipes/PatchingBuildingAndroid"},{"type":"link","label":"Pristine Expo Project","href":"/docs/recipes/PristineExpoProject","docId":"recipes/PristineExpoProject"},{"type":"link","label":"React Native Vision Camera","href":"/docs/recipes/ReactNativeVisionCamera","docId":"recipes/ReactNativeVisionCamera"},{"type":"link","label":"Redux","href":"/docs/recipes/Redux","docId":"recipes/Redux"},{"type":"link","label":"Sample YAML for CircleCi for Ignite","href":"/docs/recipes/SampleYAMLCircleCI","docId":"recipes/SampleYAMLCircleCI"},{"type":"link","label":"SelectField using `react-native-bottom-sheet`","href":"/docs/recipes/SelectFieldWithBottomSheet","docId":"recipes/SelectFieldWithBottomSheet"},{"type":"link","label":"Staying With Expo","href":"/docs/recipes/StayingWithExpo","docId":"recipes/StayingWithExpo"},{"type":"link","label":"Switch Between Expo Go and Expo CNG","href":"/docs/recipes/SwitchBetweenExpoGoCNG","docId":"recipes/SwitchBetweenExpoGoCNG"},{"type":"link","label":"TypeScript baseUrl Configuration","href":"/docs/recipes/TypeScriptBaseURL","docId":"recipes/TypeScriptBaseURL"},{"type":"link","label":"Scrolling to a location that hasn\'t been rendered using FlatList or SectionList","href":"/docs/recipes/UnrenderedItemInScrollView","docId":"recipes/UnrenderedItemInScrollView"},{"type":"link","label":"Updating Dependencies with Yarn Audit, Outdated and Upgrade","href":"/docs/recipes/UpdatingDependencies","docId":"recipes/UpdatingDependencies"},{"type":"link","label":"Using Screen Readers","href":"/docs/recipes/UsingScreenReaders","docId":"recipes/UsingScreenReaders"}],"collapsible":true}]},"docs":{"intro":{"id":"intro","title":"Intro to Recipes","description":"Welcome to the Ignite Cookbook! This is a collection of recipes for common patterns in Ignite projects.","sidebar":"mainSidebar"},"recipes/AccessibilityFontSizes":{"id":"recipes/AccessibilityFontSizes","title":"Accessiblity Font Sizes","description":"Dealing With Accessibility Font Sizes in React Native","sidebar":"mainSidebar"},"recipes/CircleCIRNSetup":{"id":"recipes/CircleCIRNSetup","title":"CircleCI CD Setup - React Native","description":"Learn how to set up your CircleCI CD instance for React Native","sidebar":"mainSidebar"},"recipes/CreatingGreateExperienceForScreenReaders":{"id":"recipes/CreatingGreateExperienceForScreenReaders","title":"Creating a Good Experience for Screen Readers","description":"Learn how to improve the experience of screen readers using your app!","sidebar":"mainSidebar"},"recipes/DetoxIntro":{"id":"recipes/DetoxIntro","title":"Detox Intro","description":"A quick look at Detox and what makes it useful","sidebar":"mainSidebar"},"recipes/DistributingAuthTokenToAPI":{"id":"recipes/DistributingAuthTokenToAPI","title":"Distributing Auth Token to APIs","description":"Use token stored in Authentication Store with API Sauce","sidebar":"mainSidebar"},"recipes/EASUpdate":{"id":"recipes/EASUpdate","title":"EAS Update","description":"Setting up Ignite to deploy over-the-air (OTA) updates via EAS","sidebar":"mainSidebar"},"recipes/EnvironmentVariables":{"id":"recipes/EnvironmentVariables","title":"Environment Variables","description":"A universal way to set up environment variables for bare and Expo projects","sidebar":"mainSidebar"},"recipes/GeneratorComponentTests":{"id":"recipes/GeneratorComponentTests","title":"Generator for Component Tests","description":"Customize `npx ignite-cli generate component` to add test files for each component generated","sidebar":"mainSidebar"},"recipes/MaestroSetup":{"id":"recipes/MaestroSetup","title":"Maestro Setup","description":"Setting up e2e testing with Maestro in Ignite","sidebar":"mainSidebar"},"recipes/MigratingToMMKV":{"id":"recipes/MigratingToMMKV","title":"Migrating to MMKV","description":"How to migrate from React Native\'s AsyncStorage to MMKV","sidebar":"mainSidebar"},"recipes/PatchingBuildingAndroid":{"id":"recipes/PatchingBuildingAndroid","title":"Patching/Building Android .aar From Source","description":"Instructions for updating the RN Android source code","sidebar":"mainSidebar"},"recipes/PristineExpoProject":{"id":"recipes/PristineExpoProject","title":"Pristine Expo Project","description":"How to remove native related code from a unified Ignite project","sidebar":"mainSidebar"},"recipes/ReactNativeVisionCamera":{"id":"recipes/ReactNativeVisionCamera","title":"React Native Vision Camera","description":"How to integrate VisionCamera in Ignite v9+","sidebar":"mainSidebar"},"recipes/Redux":{"id":"recipes/Redux","title":"Redux","description":"How to migrate a Mobx-State-Tree project to Redux","sidebar":"mainSidebar"},"recipes/SampleYAMLCircleCI":{"id":"recipes/SampleYAMLCircleCI","title":"Sample YAML for CircleCi for Ignite","description":"A Copy/Paste Sample YAML for your Ignite Project","sidebar":"mainSidebar"},"recipes/SelectFieldWithBottomSheet":{"id":"recipes/SelectFieldWithBottomSheet","title":"SelectField using `react-native-bottom-sheet`","description":"Extending Ignite\'s TextField to be used as a SelectField with react-native-bottom-sheet","sidebar":"mainSidebar"},"recipes/StayingWithExpo":{"id":"recipes/StayingWithExpo","title":"Staying With Expo","description":"Setting up Ignite to build a custom Expo development client for use with Config Plugins","sidebar":"mainSidebar"},"recipes/SwitchBetweenExpoGoCNG":{"id":"recipes/SwitchBetweenExpoGoCNG","title":"Switch Between Expo Go and Expo CNG","description":"Switch an Expo Go project to an Expo CNG project and visa versa","sidebar":"mainSidebar"},"recipes/TypeScriptBaseURL":{"id":"recipes/TypeScriptBaseURL","title":"TypeScript baseUrl Configuration","description":"How to configure TypeScript\'s baseUrl module for rewriting relative imports","sidebar":"mainSidebar"},"recipes/UnrenderedItemInScrollView":{"id":"recipes/UnrenderedItemInScrollView","title":"Scrolling to a location that hasn\'t been rendered using FlatList or SectionList","description":"This article explains how to scroll to a location of a FlatList or SectionList that hasn\'t rendered yet","sidebar":"mainSidebar"},"recipes/UpdatingDependencies":{"id":"recipes/UpdatingDependencies","title":"Updating Dependencies with Yarn Audit, Outdated and Upgrade","description":"If you get a bunch of warnings in the git command output about vulnerabilities, similar to this Github found 80 vulnerabilities on ..., you can examine these vulnerabilities with yarn audit, get a list of outdated packages with yarn outdated, and update each dependency using yarn update","sidebar":"mainSidebar"},"recipes/UsingScreenReaders":{"id":"recipes/UsingScreenReaders","title":"Using Screen Readers","description":"Learn how to use a screen reader to improve accesibility!","sidebar":"mainSidebar"}}}')}}]); \ No newline at end of file diff --git a/assets/js/935f2afb.8d3789af.js b/assets/js/935f2afb.8d3789af.js new file mode 100644 index 00000000..1234155c --- /dev/null +++ b/assets/js/935f2afb.8d3789af.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkignite_cookbook=self.webpackChunkignite_cookbook||[]).push([[53],{1109:e=>{e.exports=JSON.parse('{"pluginId":"default","version":"current","label":"Next","banner":null,"badge":false,"className":"docs-version-current","isLast":true,"docsSidebars":{"mainSidebar":[{"type":"link","label":"Intro to Recipes","href":"/docs/intro","docId":"intro"},{"type":"link","label":"Browse By Tag","href":"/docs/tags"},{"type":"category","label":"Recipes","collapsed":false,"items":[{"type":"link","label":"Accessiblity Font Sizes","href":"/docs/recipes/AccessibilityFontSizes","docId":"recipes/AccessibilityFontSizes"},{"type":"link","label":"CircleCI CD Setup - React Native","href":"/docs/recipes/CircleCIRNSetup","docId":"recipes/CircleCIRNSetup"},{"type":"link","label":"Creating a Good Experience for Screen Readers","href":"/docs/recipes/CreatingGreateExperienceForScreenReaders","docId":"recipes/CreatingGreateExperienceForScreenReaders"},{"type":"link","label":"Detox Intro","href":"/docs/recipes/DetoxIntro","docId":"recipes/DetoxIntro"},{"type":"link","label":"Distributing Auth Token to APIs","href":"/docs/recipes/DistributingAuthTokenToAPI","docId":"recipes/DistributingAuthTokenToAPI"},{"type":"link","label":"EAS Update","href":"/docs/recipes/EASUpdate","docId":"recipes/EASUpdate"},{"type":"link","label":"Environment Variables","href":"/docs/recipes/EnvironmentVariables","docId":"recipes/EnvironmentVariables"},{"type":"link","label":"Expo Router","href":"/docs/recipes/ExpoRouter","docId":"recipes/ExpoRouter"},{"type":"link","label":"Generator for Component Tests","href":"/docs/recipes/GeneratorComponentTests","docId":"recipes/GeneratorComponentTests"},{"type":"link","label":"Maestro Setup","href":"/docs/recipes/MaestroSetup","docId":"recipes/MaestroSetup"},{"type":"link","label":"Migrating to MMKV","href":"/docs/recipes/MigratingToMMKV","docId":"recipes/MigratingToMMKV"},{"type":"link","label":"Patching/Building Android .aar From Source","href":"/docs/recipes/PatchingBuildingAndroid","docId":"recipes/PatchingBuildingAndroid"},{"type":"link","label":"Pristine Expo Project","href":"/docs/recipes/PristineExpoProject","docId":"recipes/PristineExpoProject"},{"type":"link","label":"React Native Vision Camera","href":"/docs/recipes/ReactNativeVisionCamera","docId":"recipes/ReactNativeVisionCamera"},{"type":"link","label":"Redux","href":"/docs/recipes/Redux","docId":"recipes/Redux"},{"type":"link","label":"Sample YAML for CircleCi for Ignite","href":"/docs/recipes/SampleYAMLCircleCI","docId":"recipes/SampleYAMLCircleCI"},{"type":"link","label":"SelectField using `react-native-bottom-sheet`","href":"/docs/recipes/SelectFieldWithBottomSheet","docId":"recipes/SelectFieldWithBottomSheet"},{"type":"link","label":"Staying With Expo","href":"/docs/recipes/StayingWithExpo","docId":"recipes/StayingWithExpo"},{"type":"link","label":"Switch Between Expo Go and Expo CNG","href":"/docs/recipes/SwitchBetweenExpoGoCNG","docId":"recipes/SwitchBetweenExpoGoCNG"},{"type":"link","label":"TypeScript baseUrl Configuration","href":"/docs/recipes/TypeScriptBaseURL","docId":"recipes/TypeScriptBaseURL"},{"type":"link","label":"Scrolling to a location that hasn\'t been rendered using FlatList or SectionList","href":"/docs/recipes/UnrenderedItemInScrollView","docId":"recipes/UnrenderedItemInScrollView"},{"type":"link","label":"Updating Dependencies with Yarn Audit, Outdated and Upgrade","href":"/docs/recipes/UpdatingDependencies","docId":"recipes/UpdatingDependencies"},{"type":"link","label":"Using Screen Readers","href":"/docs/recipes/UsingScreenReaders","docId":"recipes/UsingScreenReaders"}],"collapsible":true}]},"docs":{"intro":{"id":"intro","title":"Intro to Recipes","description":"Welcome to the Ignite Cookbook! This is a collection of recipes for common patterns in Ignite projects.","sidebar":"mainSidebar"},"recipes/AccessibilityFontSizes":{"id":"recipes/AccessibilityFontSizes","title":"Accessiblity Font Sizes","description":"Dealing With Accessibility Font Sizes in React Native","sidebar":"mainSidebar"},"recipes/CircleCIRNSetup":{"id":"recipes/CircleCIRNSetup","title":"CircleCI CD Setup - React Native","description":"Learn how to set up your CircleCI CD instance for React Native","sidebar":"mainSidebar"},"recipes/CreatingGreateExperienceForScreenReaders":{"id":"recipes/CreatingGreateExperienceForScreenReaders","title":"Creating a Good Experience for Screen Readers","description":"Learn how to improve the experience of screen readers using your app!","sidebar":"mainSidebar"},"recipes/DetoxIntro":{"id":"recipes/DetoxIntro","title":"Detox Intro","description":"A quick look at Detox and what makes it useful","sidebar":"mainSidebar"},"recipes/DistributingAuthTokenToAPI":{"id":"recipes/DistributingAuthTokenToAPI","title":"Distributing Auth Token to APIs","description":"Use token stored in Authentication Store with API Sauce","sidebar":"mainSidebar"},"recipes/EASUpdate":{"id":"recipes/EASUpdate","title":"EAS Update","description":"Setting up Ignite to deploy over-the-air (OTA) updates via EAS","sidebar":"mainSidebar"},"recipes/EnvironmentVariables":{"id":"recipes/EnvironmentVariables","title":"Environment Variables","description":"A universal way to set up environment variables for bare and Expo projects","sidebar":"mainSidebar"},"recipes/ExpoRouter":{"id":"recipes/ExpoRouter","title":"Expo Router","description":"How to convert Ignite v9 demo app to utilize `expo-router`","sidebar":"mainSidebar"},"recipes/GeneratorComponentTests":{"id":"recipes/GeneratorComponentTests","title":"Generator for Component Tests","description":"Customize `npx ignite-cli generate component` to add test files for each component generated","sidebar":"mainSidebar"},"recipes/MaestroSetup":{"id":"recipes/MaestroSetup","title":"Maestro Setup","description":"Setting up e2e testing with Maestro in Ignite","sidebar":"mainSidebar"},"recipes/MigratingToMMKV":{"id":"recipes/MigratingToMMKV","title":"Migrating to MMKV","description":"How to migrate from React Native\'s AsyncStorage to MMKV","sidebar":"mainSidebar"},"recipes/PatchingBuildingAndroid":{"id":"recipes/PatchingBuildingAndroid","title":"Patching/Building Android .aar From Source","description":"Instructions for updating the RN Android source code","sidebar":"mainSidebar"},"recipes/PristineExpoProject":{"id":"recipes/PristineExpoProject","title":"Pristine Expo Project","description":"How to remove native related code from a unified Ignite project","sidebar":"mainSidebar"},"recipes/ReactNativeVisionCamera":{"id":"recipes/ReactNativeVisionCamera","title":"React Native Vision Camera","description":"How to integrate VisionCamera in Ignite v9+","sidebar":"mainSidebar"},"recipes/Redux":{"id":"recipes/Redux","title":"Redux","description":"How to migrate a Mobx-State-Tree project to Redux","sidebar":"mainSidebar"},"recipes/SampleYAMLCircleCI":{"id":"recipes/SampleYAMLCircleCI","title":"Sample YAML for CircleCi for Ignite","description":"A Copy/Paste Sample YAML for your Ignite Project","sidebar":"mainSidebar"},"recipes/SelectFieldWithBottomSheet":{"id":"recipes/SelectFieldWithBottomSheet","title":"SelectField using `react-native-bottom-sheet`","description":"Extending Ignite\'s TextField to be used as a SelectField with react-native-bottom-sheet","sidebar":"mainSidebar"},"recipes/StayingWithExpo":{"id":"recipes/StayingWithExpo","title":"Staying With Expo","description":"Setting up Ignite to build a custom Expo development client for use with Config Plugins","sidebar":"mainSidebar"},"recipes/SwitchBetweenExpoGoCNG":{"id":"recipes/SwitchBetweenExpoGoCNG","title":"Switch Between Expo Go and Expo CNG","description":"Switch an Expo Go project to an Expo CNG project and visa versa","sidebar":"mainSidebar"},"recipes/TypeScriptBaseURL":{"id":"recipes/TypeScriptBaseURL","title":"TypeScript baseUrl Configuration","description":"How to configure TypeScript\'s baseUrl module for rewriting relative imports","sidebar":"mainSidebar"},"recipes/UnrenderedItemInScrollView":{"id":"recipes/UnrenderedItemInScrollView","title":"Scrolling to a location that hasn\'t been rendered using FlatList or SectionList","description":"This article explains how to scroll to a location of a FlatList or SectionList that hasn\'t rendered yet","sidebar":"mainSidebar"},"recipes/UpdatingDependencies":{"id":"recipes/UpdatingDependencies","title":"Updating Dependencies with Yarn Audit, Outdated and Upgrade","description":"If you get a bunch of warnings in the git command output about vulnerabilities, similar to this Github found 80 vulnerabilities on ..., you can examine these vulnerabilities with yarn audit, get a list of outdated packages with yarn outdated, and update each dependency using yarn update","sidebar":"mainSidebar"},"recipes/UsingScreenReaders":{"id":"recipes/UsingScreenReaders","title":"Using Screen Readers","description":"Learn how to use a screen reader to improve accesibility!","sidebar":"mainSidebar"}}}')}}]); \ No newline at end of file diff --git a/assets/js/94ee064e.070613cd.js b/assets/js/94ee064e.070613cd.js new file mode 100644 index 00000000..f640d746 --- /dev/null +++ b/assets/js/94ee064e.070613cd.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkignite_cookbook=self.webpackChunkignite_cookbook||[]).push([[8083],{1908:e=>{e.exports=JSON.parse('{"label":"react-navigation","permalink":"/docs/tags/react-navigation","allTagsPath":"/docs/tags","count":1,"items":[{"id":"recipes/ExpoRouter","title":"Expo Router","description":"How to convert Ignite v9 demo app to utilize `expo-router`","permalink":"/docs/recipes/ExpoRouter"}]}')}}]); \ No newline at end of file diff --git a/assets/js/c47fa949.0e2d72e7.js b/assets/js/c47fa949.0e2d72e7.js new file mode 100644 index 00000000..74dfdd96 --- /dev/null +++ b/assets/js/c47fa949.0e2d72e7.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkignite_cookbook=self.webpackChunkignite_cookbook||[]).push([[6932],{3905:(e,n,t)=>{t.d(n,{Zo:()=>c,kt:()=>u});var o=t(7294);function r(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function a(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);n&&(o=o.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,o)}return t}function i(e){for(var n=1;n=0||(r[t]=e[t]);return r}(e,n);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(o=0;o=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(r[t]=e[t])}return r}var l=o.createContext({}),p=function(e){var n=o.useContext(l),t=n;return e&&(t="function"==typeof e?e(n):i(i({},n),e)),t},c=function(e){var n=p(e.components);return o.createElement(l.Provider,{value:n},e.children)},m={inlineCode:"code",wrapper:function(e){var n=e.children;return o.createElement(o.Fragment,{},n)}},d=o.forwardRef((function(e,n){var t=e.components,r=e.mdxType,a=e.originalType,l=e.parentName,c=s(e,["components","mdxType","originalType","parentName"]),d=p(t),u=r,g=d["".concat(l,".").concat(u)]||d[u]||m[u]||a;return t?o.createElement(g,i(i({ref:n},c),{},{components:t})):o.createElement(g,i({ref:n},c))}));function u(e,n){var t=arguments,r=n&&n.mdxType;if("string"==typeof e||r){var a=t.length,i=new Array(a);i[0]=d;var s={};for(var l in n)hasOwnProperty.call(n,l)&&(s[l]=n[l]);s.originalType=e,s.mdxType="string"==typeof e?e:r,i[1]=s;for(var p=2;p{t.r(n),t.d(n,{assets:()=>l,contentTitle:()=>i,default:()=>m,frontMatter:()=>a,metadata:()=>s,toc:()=>p});var o=t(7462),r=(t(7294),t(3905));const a={title:"Expo Router",description:"How to convert Ignite v9 demo app to utilize `expo-router`",tags:["Expo","expo-router","react-navigation"],last_update:{author:"Frank Calise & Justin Poliachik"},publish_date:new Date("2024-01-25T00:00:00.000Z")},i="Expo Router",s={unversionedId:"recipes/ExpoRouter",id:"recipes/ExpoRouter",title:"Expo Router",description:"How to convert Ignite v9 demo app to utilize `expo-router`",source:"@site/docs/recipes/ExpoRouter.md",sourceDirName:"recipes",slug:"/recipes/ExpoRouter",permalink:"/docs/recipes/ExpoRouter",draft:!1,tags:[{label:"Expo",permalink:"/docs/tags/expo"},{label:"expo-router",permalink:"/docs/tags/expo-router"},{label:"react-navigation",permalink:"/docs/tags/react-navigation"}],version:"current",lastUpdatedBy:"Frank Calise & Justin Poliachik",lastUpdatedAt:1707517098,formattedLastUpdatedAt:"Feb 9, 2024",frontMatter:{title:"Expo Router",description:"How to convert Ignite v9 demo app to utilize `expo-router`",tags:["Expo","expo-router","react-navigation"],last_update:{author:"Frank Calise & Justin Poliachik"},publish_date:"2024-01-25T00:00:00.000Z"},sidebar:"mainSidebar",previous:{title:"Environment Variables",permalink:"/docs/recipes/EnvironmentVariables"},next:{title:"Generator for Component Tests",permalink:"/docs/recipes/GeneratorComponentTests"}},l={},p=[{value:"Overview",id:"overview",level:2},{value:"Installation and Project Configuration",id:"installation-and-project-configuration",level:2},{value:"Reworking the Directory Structure",id:"reworking-the-directory-structure",level:2},{value:"Fix Imports",id:"fix-imports",level:3},{value:"Creating File-based Routes",id:"creating-file-based-routes",level:2},{value:"src/app/_layout.tsx",id:"srcapp_layouttsx",level:3},{value:"src/app/(app)/_layout.tsx",id:"srcappapp_layouttsx",level:3},{value:"src/app/log-in.tsx",id:"srcapplog-intsx",level:3},{value:"src/app/(app)/index.tsx",id:"srcappappindextsx",level:3},{value:"Checkpoint",id:"checkpoint",level:3},{value:"Adding Tab Navigation",id:"adding-tab-navigation",level:2},{value:"Creating Tab Screens",id:"creating-tab-screens",level:3},{value:"Showroom Screen",id:"showroom-screen",level:3},{value:"Code Cleanup",id:"code-cleanup",level:2},{value:"Summary",id:"summary",level:2},{value:"Additional Resources",id:"additional-resources",level:2}],c={toc:p};function m(e){let{components:n,...t}=e;return(0,r.kt)("wrapper",(0,o.Z)({},c,t,{components:n,mdxType:"MDXLayout"}),(0,r.kt)("h1",{id:"expo-router"},"Expo Router"),(0,r.kt)("h2",{id:"overview"},"Overview"),(0,r.kt)("p",null,"Expo Router brings file-based routing to React Native and web applications allowing you to easily create universal apps. Whenever a file is added to your ",(0,r.kt)("inlineCode",{parentName:"p"},"src/app")," directory, a new path is automatically added to your navigation."),(0,r.kt)("p",null,"For the full documentation by ",(0,r.kt)("a",{parentName:"p",href:"https://expo.dev"},"Expo"),", head on over to the ",(0,r.kt)("a",{parentName:"p",href:"https://docs.expo.dev/routing/introduction/"},"Introduction to Expo Router"),"."),(0,r.kt)("p",null,"Ignite v9 is fully equipped to utilize ",(0,r.kt)("inlineCode",{parentName:"p"},"expo-router")," after dependency installation and some directory structure updates! In this recipe, we'll convert the demo app's auth and tab navigators from ",(0,r.kt)("inlineCode",{parentName:"p"},"react-navigation")," to use ",(0,r.kt)("inlineCode",{parentName:"p"},"expo-router"),"."),(0,r.kt)("h2",{id:"installation-and-project-configuration"},"Installation and Project Configuration"),(0,r.kt)("p",null,"Bootstrap a new Ignite project:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-terminal"},"npx ignite-cli@next new pizza-router --yes\ncd pizza-router\n")),(0,r.kt)("p",null,"Add the missing dependencies ",(0,r.kt)("inlineCode",{parentName:"p"},"expo-router")," needs:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-terminal"},"npx expo install expo-router expo-constants\n")),(0,r.kt)("p",null,"Add ",(0,r.kt)("inlineCode",{parentName:"p"},"expo-router")," to ",(0,r.kt)("inlineCode",{parentName:"p"},"app.json")," plugins list if necessary:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-json"},'"plugins": [\n ...\n "expo-font",\n // success-line\n "expo-router"\n],\n')),(0,r.kt)("p",null,"Change the entry point that ",(0,r.kt)("inlineCode",{parentName:"p"},"expo-router")," expects in ",(0,r.kt)("inlineCode",{parentName:"p"},"package.json"),":"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-json"},'// error-line\n"main": "node_modules/expo/AppEntry.js",\n// success-line\n"main": "expo-router/entry",\n')),(0,r.kt)("p",null,(0,r.kt)("inlineCode",{parentName:"p"},"expo-router")," has great ",(0,r.kt)("a",{parentName:"p",href:"https://docs.expo.dev/router/reference/typed-routes/"},"TypeScript support"),", so let's enable that in ",(0,r.kt)("inlineCode",{parentName:"p"},"app.json")," under ",(0,r.kt)("inlineCode",{parentName:"p"},"experiments"),"."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-json"},'{\n "expo": {\n "experiments": {\n "tsconfigPaths": true,\n // success-line\n "typedRoutes": true\n }\n }\n}\n')),(0,r.kt)("h2",{id:"reworking-the-directory-structure"},"Reworking the Directory Structure"),(0,r.kt)("p",null,"Expo Router requires route files to live in either ",(0,r.kt)("inlineCode",{parentName:"p"},"app")," or ",(0,r.kt)("inlineCode",{parentName:"p"},"src/app")," directories. But since our Ignite project is already using ",(0,r.kt)("inlineCode",{parentName:"p"},"app"),", we'll need to rename it to ",(0,r.kt)("inlineCode",{parentName:"p"},"src"),". We'll create ",(0,r.kt)("inlineCode",{parentName:"p"},"src/app")," to contain all the file-base routing files from here on out, and models, components and other shared files will be located in the ",(0,r.kt)("inlineCode",{parentName:"p"},"src")," directory now. We'll also remove ",(0,r.kt)("inlineCode",{parentName:"p"},"App.tsx")," as this is no longer the entry point of the application."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-terminal"},"rm App.tsx\nmv app src\nmkdir src/app\n")),(0,r.kt)("p",null,"Let's update the TS alias and include paths over in ",(0,r.kt)("inlineCode",{parentName:"p"},"tsconfig.json")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-json"},'{\n "compilerOptions": {\n // ...\n "paths": {\n // error-line\n "app/*": ["./app/*"],\n // success-line\n "src/*": ["./src/*"],\n // ...\n },\n }\n // error-line-start\n "include": [\n "index.js",\n "App.tsx",\n "app",\n "types",\n "plugins",\n "app.config.ts",\n ".expo/types/**/*.ts",\n "expo-env.d.ts"\n ],\n // error-line-end\n // success-line\n "include": ["**/*.ts", "**/*.tsx"],\n // ...\n}\n')),(0,r.kt)("h3",{id:"fix-imports"},"Fix Imports"),(0,r.kt)("p",null,"We also need to fix up a few imports to use ",(0,r.kt)("inlineCode",{parentName:"p"},"src/")," instead of ",(0,r.kt)("inlineCode",{parentName:"p"},"app/"),".\nIgnite's Demo App only contains a few files we need to update, but an existing app could contain more."),(0,r.kt)("p",null,(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"package.json"))),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-json"},'// error-line-start\n"format": "prettier --write \\"app/**/*.{js,jsx,json,md,ts,tsx}\\"",\n"lint": "eslint App.tsx app test --fix --ext .js,.ts,.tsx && npm run format",\n// error-line-end\n// success-line-start\n"format": "prettier --write \\"src/**/*.{js,jsx,json,md,ts,tsx}\\"",\n"lint": "eslint src test --fix --ext .js,.ts,.tsx && npm run format",\n// success-line-end\n')),(0,r.kt)("p",null,(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"src/devtools/ReactotronConfig.ts"))),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-ts"},'// error-line-start\nimport { clear } from "app/utils/storage";\nimport { goBack, resetRoot, navigate } from "app/navigators/navigationUtilities";\n// error-line-end\n// success-line-start\nimport { clear } from "src/utils/storage";\nimport { goBack, resetRoot, navigate } from "src/navigators/navigationUtilities";\n// success-line-end\n')),(0,r.kt)("p",null,(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"src/components/ListView.ts"))),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-ts"},'// error-line\nimport { isRTL } from "app/i18n";\n// success-line\nimport { isRTL } from "src/i18n";\n')),(0,r.kt)("details",null,(0,r.kt)("summary",null,"(optional) Additional files to update"),(0,r.kt)("p",null,(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"test/i18n.test.ts"))),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-ts"},'// error-line\nimport en from "../app/i18n/en";\n// success-line\nimport en from "../src/i18n/en";\nimport { exec } from "child_process";\n')),(0,r.kt)("p",null,(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"ignite/templates/component/NAME.tsx.ejs"))),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-js"},'---\npatch:\n // error-line\n path: "app/components/index.ts"\n // success-line\n path: "src/components/index.ts"\n append: "export * from \\"./<%= props.subdirectory %><%= props.pascalCaseName %>\\"\\n"\n skip: <%= props.skipIndexFile %>\n---\nimport * as React from "react"\nimport { StyleProp, TextStyle, View, ViewStyle } from "react-native"\nimport { observer } from "mobx-react-lite"\n// error-line-start\nimport { colors, typography } from "app/theme"\nimport { Text } from "app/components/Text"\n// error-line-end\n// success-line-start\nimport { colors, typography } from "src/theme"\nimport { Text } from "src/components/Text"\n// success-line-end\n')),(0,r.kt)("p",null,(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"ignite/templates/model/NAME.tsx.ejs"))),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-js"},'---\npatches:\n// error-line\n- path: "app/models/RootStore.ts"\n// success-line\n- path: "src/models/RootStore.ts"\n after: "from \\"mobx-state-tree\\"\\n"\n insert: "import { <%= props.pascalCaseName %>Model } from \\"./<%= props.pascalCaseName %>\\"\\n"\n skip: <%= !props.pascalCaseName.endsWith(\'Store\') %>\n// error-line\n- path: "app/models/RootStore.ts"\n// success-line\n- path: "src/models/RootStore.ts"\n after: "types.model(\\"RootStore\\").props({\\n"\n insert: " <%= props.camelCaseName %>: types.optional(<%= props.pascalCaseName %>Model, {} as any),\\n"\n skip: <%= !props.pascalCaseName.endsWith(\'Store\') %>\n// error-line\n- path: "app/models/index.ts"\n// success-line\n- path: "src/models/index.ts"\n\n'))),(0,r.kt)("h2",{id:"creating-file-based-routes"},"Creating File-based Routes"),(0,r.kt)("h3",{id:"srcapp_layouttsx"},"src/app/","_","layout.tsx"),(0,r.kt)("p",null,"We're now ready to start setting up navigation for the app! If you're familiar with Ignite, ",(0,r.kt)("inlineCode",{parentName:"p"},"app.tsx")," is where our root navigator lives, however, with ",(0,r.kt)("inlineCode",{parentName:"p"},"expo-router"),", we'll use ",(0,r.kt)("inlineCode",{parentName:"p"},"src/app/_layout.tsx")," for that. We'll add the providers here that any route would need within the app."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-tsx"},'// app/_layout.tsx\nimport React from "react";\nimport { Slot, SplashScreen } from "expo-router";\nimport { useInitialRootStore } from "src/models";\n\nSplashScreen.preventAutoHideAsync();\n\nif (__DEV__) {\n // Load Reactotron configuration in development. We don\'t want to\n // include this in our production bundle, so we are using `if (__DEV__)`\n // to only execute this in development.\n require("src/devtools/ReactotronConfig.ts");\n}\n\nexport { ErrorBoundary } from "src/components/ErrorBoundary/ErrorBoundary";\n\nexport default function Root() {\n // Wait for stores to load and render our layout inside of it so we have access\n // to auth info etc\n const { rehydrated } = useInitialRootStore();\n if (!rehydrated) {\n return null;\n }\n\n return ;\n}\n')),(0,r.kt)("p",null,"Move ",(0,r.kt)("inlineCode",{parentName:"p"},"ErrorBoundary")," out of ",(0,r.kt)("inlineCode",{parentName:"p"},"screens/ErrorScreen")," and into ",(0,r.kt)("inlineCode",{parentName:"p"},"src/components/ErrorBoundary"),":"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-terminal"},"mkdir src/components/ErrorBoundary\nmv src/screens/ErrorScreen/* src/components/ErrorBoundary\n")),(0,r.kt)("p",null,"For starters, this sets up our error boundary for the app and handles waiting on our stores to rehydrate. ",(0,r.kt)("inlineCode",{parentName:"p"},"")," comes from ",(0,r.kt)("inlineCode",{parentName:"p"},"expo-router"),", you can think of it like the ",(0,r.kt)("inlineCode",{parentName:"p"},"children")," prop in ",(0,r.kt)("inlineCode",{parentName:"p"},"React"),". This component can be wrapped with others to help create a layout."),(0,r.kt)("p",null,"Next, we'll convert the conditional part of authentication from ",(0,r.kt)("inlineCode",{parentName:"p"},"react-navigation")," to ",(0,r.kt)("inlineCode",{parentName:"p"},"expo-router"),", deciding on whether or not to display the login form or get to the welcome screen experience."),(0,r.kt)("h3",{id:"srcappapp_layouttsx"},"src/app/(app)/","_","layout.tsx"),(0,r.kt)("p",null,"Create another ",(0,r.kt)("inlineCode",{parentName:"p"},"_layout.tsx")," but this time inside of a new directory, ",(0,r.kt)("inlineCode",{parentName:"p"},"src/app/(app)"),". This route wrapped in parentheses is called a ",(0,r.kt)("a",{parentName:"p",href:"https://docs.expo.dev/routing/layouts/#groups"},"Group"),". Groups can be used to add layouts and/or help organize sections of the app without adding additional segments to the URL. Remember, each directory is a route in this new mental model of file-based routing - but sometimes we don't want that, that's when you'll call upon groups."),(0,r.kt)("p",null,"In this layout is where we'll determine if the user is authenticated by checking our MST store. We'll also wait here while assets are loaded and then hide the splash screen when finished."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-tsx"},'import React from "react";\nimport { Redirect, SplashScreen, Stack } from "expo-router";\nimport { observer } from "mobx-react-lite";\nimport { useStores } from "src/models";\nimport { useFonts } from "expo-font";\nimport { customFontsToLoad } from "src/theme";\n\nexport default observer(function Layout() {\n const {\n authenticationStore: { isAuthenticated },\n } = useStores();\n\n const [fontsLoaded, fontError] = useFonts(customFontsToLoad);\n\n React.useEffect(() => {\n if (fontsLoaded || fontError) {\n // Hide the splash screen after the fonts have loaded and the UI is ready.\n SplashScreen.hideAsync();\n }\n }, [fontsLoaded, fontError]);\n\n if (!fontsLoaded && !fontError) {\n return null;\n }\n\n if (!isAuthenticated) {\n return ;\n }\n\n return ;\n});\n')),(0,r.kt)("p",null,"As you can see, if the user is not authenticated we redirect them to the ",(0,r.kt)("inlineCode",{parentName:"p"},"/log-in")," route, otherwise we'll render a stack navigator. TypeScript is probably telling us that route doesn't exist yet, so let's fix that."),(0,r.kt)("h3",{id:"srcapplog-intsx"},"src/app/log-in.tsx"),(0,r.kt)("p",null,"To redirect the user to the login form, create ",(0,r.kt)("inlineCode",{parentName:"p"},"src/app/log-in.tsx"),". We'll copy over the contents from the original boilerplate ",(0,r.kt)("inlineCode",{parentName:"p"},"src/screens/LoginScreen.tsx")," to help the UI layout of this page."),(0,r.kt)("details",null,(0,r.kt)("summary",null,"src/app/log-in.tsx"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-tsx"},'import { router } from "expo-router";\nimport { observer } from "mobx-react-lite";\nimport React, { ComponentType, useEffect, useMemo, useRef, useState } from "react";\nimport { TextInput, TextStyle, ViewStyle } from "react-native";\nimport { Button, Icon, Screen, Text, TextField, TextFieldAccessoryProps } from "src/components";\nimport { useStores } from "src/models";\nimport { colors, spacing } from "src/theme";\n\nexport default observer(function Login(_props) {\n const authPasswordInput = useRef(null);\n\n const [authPassword, setAuthPassword] = useState("");\n const [isAuthPasswordHidden, setIsAuthPasswordHidden] = useState(true);\n const [isSubmitted, setIsSubmitted] = useState(false);\n const [attemptsCount, setAttemptsCount] = useState(0);\n const {\n authenticationStore: { authEmail, setAuthEmail, setAuthToken, validationError },\n } = useStores();\n\n useEffect(() => {\n // Here is where you could fetch credentials from keychain or storage\n // and pre-fill the form fields.\n setAuthEmail("ignite@infinite.red");\n setAuthPassword("ign1teIsAwes0m3");\n\n // Return a "cleanup" function that React will run when the component unmounts\n return () => {\n setAuthPassword("");\n setAuthEmail("");\n };\n }, []);\n\n const error = isSubmitted ? validationError : "";\n\n function login() {\n setIsSubmitted(true);\n setAttemptsCount(attemptsCount + 1);\n\n if (validationError) return;\n\n // Make a request to your server to get an authentication token.\n // If successful, reset the fields and set the token.\n setIsSubmitted(false);\n setAuthPassword("");\n setAuthEmail("");\n\n // We\'ll mock this with a fake token.\n setAuthToken(String(Date.now()));\n\n // navigate to the main screen\n router.replace("/");\n }\n\n const PasswordRightAccessory: ComponentType = useMemo(\n () =>\n function PasswordRightAccessory(props: TextFieldAccessoryProps) {\n return (\n setIsAuthPasswordHidden(!isAuthPasswordHidden)}\n />\n );\n },\n [isAuthPasswordHidden]\n );\n\n return (\n \n \n \n {attemptsCount > 2 && }\n\n authPasswordInput.current?.focus()}\n />\n\n \n\n \n }\n />\n );\n});\n\nconst $screenContentContainer: ViewStyle = {\n flex: 1,\n};\n\nconst $listContentContainer: ContentStyle = {\n paddingHorizontal: spacing.lg,\n paddingTop: spacing.lg + spacing.xl,\n paddingBottom: spacing.lg,\n};\n\nconst $heading: ViewStyle = {\n marginBottom: spacing.md,\n};\n\nconst $item: ViewStyle = {\n padding: spacing.md,\n marginTop: spacing.md,\n minHeight: 120,\n};\n\nconst $itemThumbnail: ImageStyle = {\n marginTop: spacing.sm,\n borderRadius: 50,\n alignSelf: "flex-start",\n};\n\nconst $toggle: ViewStyle = {\n marginTop: spacing.md,\n};\n\nconst $labelStyle: TextStyle = {\n textAlign: "left",\n};\n\nconst $iconContainer: ViewStyle = {\n height: ICON_SIZE,\n width: ICON_SIZE,\n flexDirection: "row",\n marginEnd: spacing.sm,\n};\n\nconst $metadata: TextStyle = {\n color: colors.textDim,\n marginTop: spacing.xs,\n flexDirection: "row",\n};\n\nconst $metadataText: TextStyle = {\n color: colors.textDim,\n marginEnd: spacing.md,\n marginBottom: spacing.xs,\n};\n\nconst $favoriteButton: ViewStyle = {\n borderRadius: 17,\n marginTop: spacing.md,\n justifyContent: "flex-start",\n backgroundColor: colors.palette.neutral300,\n borderColor: colors.palette.neutral300,\n paddingHorizontal: spacing.md,\n paddingTop: spacing.xxxs,\n paddingBottom: 0,\n minHeight: 32,\n alignSelf: "flex-start",\n};\n\nconst $unFavoriteButton: ViewStyle = {\n borderColor: colors.palette.primary100,\n backgroundColor: colors.palette.primary100,\n};\n\nconst $emptyState: ViewStyle = {\n marginTop: spacing.xxl,\n};\n\nconst $emptyStateImage: ImageStyle = {\n transform: [{ scaleX: isRTL ? -1 : 1 }],\n};\n'))),(0,r.kt)("details",null,(0,r.kt)("summary",null,"src/app/(app)/(tabs)/debug.tsx"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-tsx"},'import React from "react";\nimport * as Application from "expo-application";\nimport { Linking, Platform, TextStyle, View, ViewStyle } from "react-native";\nimport { Button, ListItem, Screen, Text } from "src/components";\nimport { colors, spacing } from "src/theme";\nimport { isRTL } from "src/i18n";\nimport { useStores } from "src/models";\n\nfunction openLinkInBrowser(url: string) {\n Linking.canOpenURL(url).then((canOpen) => canOpen && Linking.openURL(url));\n}\n\nexport default function DemoDebugScreen() {\n const {\n authenticationStore: { logout },\n } = useStores();\n\n const usingHermes = typeof HermesInternal === "object" && HermesInternal !== null;\n // @ts-expect-error\n const usingFabric = global.nativeFabricUIManager != null;\n\n const demoReactotron = React.useMemo(\n () => async () => {\n if (__DEV__) {\n console.tron.display({\n name: "DISPLAY",\n value: {\n appId: Application.applicationId,\n appName: Application.applicationName,\n appVersion: Application.nativeApplicationVersion,\n appBuildVersion: Application.nativeBuildVersion,\n hermesEnabled: usingHermes,\n },\n important: true,\n });\n }\n },\n []\n );\n\n return (\n \n openLinkInBrowser("https://github.com/infinitered/ignite/issues")}\n />\n \n \n \n App Id\n {Application.applicationId}\n \n }\n />\n \n App Name\n {Application.applicationName}\n \n }\n />\n \n App Version\n {Application.nativeApplicationVersion}\n \n }\n />\n \n App Build Version\n {Application.nativeBuildVersion}\n \n }\n />\n \n Hermes Enabled\n {String(usingHermes)}\n \n }\n />\n \n Fabric Enabled\n {String(usingFabric)}\n \n }\n />\n \n \n \\n }\\n />\\n );\\n});\\n\\nconst $screenContentContainer: ViewStyle = {\\n flex: 1,\\n};\\n\\nconst $listContentContainer: ContentStyle = {\\n paddingHorizontal: spacing.lg,\\n paddingTop: spacing.lg + spacing.xl,\\n paddingBottom: spacing.lg,\\n};\\n\\nconst $heading: ViewStyle = {\\n marginBottom: spacing.md,\\n};\\n\\nconst $item: ViewStyle = {\\n padding: spacing.md,\\n marginTop: spacing.md,\\n minHeight: 120,\\n};\\n\\nconst $itemThumbnail: ImageStyle = {\\n marginTop: spacing.sm,\\n borderRadius: 50,\\n alignSelf: \\"flex-start\\",\\n};\\n\\nconst $toggle: ViewStyle = {\\n marginTop: spacing.md,\\n};\\n\\nconst $labelStyle: TextStyle = {\\n textAlign: \\"left\\",\\n};\\n\\nconst $iconContainer: ViewStyle = {\\n height: ICON_SIZE,\\n width: ICON_SIZE,\\n flexDirection: \\"row\\",\\n marginEnd: spacing.sm,\\n};\\n\\nconst $metadata: TextStyle = {\\n color: colors.textDim,\\n marginTop: spacing.xs,\\n flexDirection: \\"row\\",\\n};\\n\\nconst $metadataText: TextStyle = {\\n color: colors.textDim,\\n marginEnd: spacing.md,\\n marginBottom: spacing.xs,\\n};\\n\\nconst $favoriteButton: ViewStyle = {\\n borderRadius: 17,\\n marginTop: spacing.md,\\n justifyContent: \\"flex-start\\",\\n backgroundColor: colors.palette.neutral300,\\n borderColor: colors.palette.neutral300,\\n paddingHorizontal: spacing.md,\\n paddingTop: spacing.xxxs,\\n paddingBottom: 0,\\n minHeight: 32,\\n alignSelf: \\"flex-start\\",\\n};\\n\\nconst $unFavoriteButton: ViewStyle = {\\n borderColor: colors.palette.primary100,\\n backgroundColor: colors.palette.primary100,\\n};\\n\\nconst $emptyState: ViewStyle = {\\n marginTop: spacing.xxl,\\n};\\n\\nconst $emptyStateImage: ImageStyle = {\\n transform: [{ scaleX: isRTL ? -1 : 1 }],\\n};\\n\\nimport React from \\"react\\";\\nimport * as Application from \\"expo-application\\";\\nimport { Linking, Platform, TextStyle, View, ViewStyle } from \\"react-native\\";\\nimport { Button, ListItem, Screen, Text } from \\"src/components\\";\\nimport { colors, spacing } from \\"src/theme\\";\\nimport { isRTL } from \\"src/i18n\\";\\nimport { useStores } from \\"src/models\\";\\n\\nfunction openLinkInBrowser(url: string) {\\n Linking.canOpenURL(url).then((canOpen) => canOpen && Linking.openURL(url));\\n}\\n\\nexport default function DemoDebugScreen() {\\n const {\\n authenticationStore: { logout },\\n } = useStores();\\n\\n const usingHermes = typeof HermesInternal === \\"object\\" && HermesInternal !== null;\\n // @ts-expect-error\\n const usingFabric = global.nativeFabricUIManager != null;\\n\\n const demoReactotron = React.useMemo(\\n () => async () => {\\n if (__DEV__) {\\n console.tron.display({\\n name: \\"DISPLAY\\",\\n value: {\\n appId: Application.applicationId,\\n appName: Application.applicationName,\\n appVersion: Application.nativeApplicationVersion,\\n appBuildVersion: Application.nativeBuildVersion,\\n hermesEnabled: usingHermes,\\n },\\n important: true,\\n });\\n }\\n },\\n []\\n );\\n\\n return (\\n \\n openLinkInBrowser(\\"https://github.com/infinitered/ignite/issues\\")}\\n />\\n \\n \\n \\n App Id\\n {Application.applicationId}\\n \\n }\\n />\\n \\n App Name\\n {Application.applicationName}\\n \\n }\\n />\\n \\n App Version\\n {Application.nativeApplicationVersion}\\n \\n }\\n />\\n \\n App Build Version\\n {Application.nativeBuildVersion}\\n \\n }\\n />\\n \\n Hermes Enabled\\n {String(usingHermes)}\\n \\n }\\n />\\n \\n Fabric Enabled\\n {String(usingFabric)}\\n \\n }\\n />\\n \\n \\n

Welcome to the Ignite Cookbook 👋

This is a collection of recipes for common patterns that we use sometimes at Infinite Red or in the Ignite community but don't quite belong in the Ignite boilerplate directly. We'll be adding to this over time, so be sure to check back often!

What is a Recipe?

A recipe is a collection of steps that you can follow to accomplish a common task or pattern in your Ignite project. Recipes are written to be as simple as possible, and are meant to be a starting point for you to build upon. You can use them as-is, or you can use them as a reference to help you create your own solutions.

Who is this for?

This is for anyone who wants to extend their Ignite-based React Native app with additional functionality, and how to use it to build their own apps. You don't need to be an expert in React Native or Ignite to follow along. If you're new to Ignite, we recommend you start with the new docs page to explore the boilerplate. You can also use these patterns if you're not using Ignite, as in the end Ignite is just React Native!

Are these recipes tested and up-to-date?

All recipes are written or reviewed by the Ignite team, and are also reviewed by the community. If you find a recipe that is out of date, or doesn't work, please open an issue. It's our goal to keep these recipes up to date and working, so we appreciate your help!

Backed by the Ignite Team & Community

The Ignite Cookbook is maintained by the Infinite Red team, and the community. If you have any questions, or want to contribute, please join our Slack and say hi!

Have an idea for a recipe?

We'd love to hear it! Please open an issue and we'll review it. We're always looking for new ideas to add to the cookbook!

Is this page still up to date? Did it work for you?

- - +

Welcome to the Ignite Cookbook 👋

This is a collection of recipes for common patterns that we use sometimes at Infinite Red or in the Ignite community but don't quite belong in the Ignite boilerplate directly. We'll be adding to this over time, so be sure to check back often!

What is a Recipe?

A recipe is a collection of steps that you can follow to accomplish a common task or pattern in your Ignite project. Recipes are written to be as simple as possible, and are meant to be a starting point for you to build upon. You can use them as-is, or you can use them as a reference to help you create your own solutions.

Who is this for?

This is for anyone who wants to extend their Ignite-based React Native app with additional functionality, and how to use it to build their own apps. You don't need to be an expert in React Native or Ignite to follow along. If you're new to Ignite, we recommend you start with the new docs page to explore the boilerplate. You can also use these patterns if you're not using Ignite, as in the end Ignite is just React Native!

Are these recipes tested and up-to-date?

All recipes are written or reviewed by the Ignite team, and are also reviewed by the community. If you find a recipe that is out of date, or doesn't work, please open an issue. It's our goal to keep these recipes up to date and working, so we appreciate your help!

Backed by the Ignite Team & Community

The Ignite Cookbook is maintained by the Infinite Red team, and the community. If you have any questions, or want to contribute, please join our Slack and say hi!

Have an idea for a recipe?

We'd love to hear it! Please open an issue and we'll review it. We're always looking for new ideas to add to the cookbook!

Is this page still up to date? Did it work for you?

+ + \ No newline at end of file diff --git a/docs/recipes/AccessibilityFontSizes/index.html b/docs/recipes/AccessibilityFontSizes/index.html index b8e495bc..2fa18f1e 100644 --- a/docs/recipes/AccessibilityFontSizes/index.html +++ b/docs/recipes/AccessibilityFontSizes/index.html @@ -8,8 +8,8 @@ Accessiblity Font Sizes | Ignite Cookbook for React Native - - + +
@@ -35,8 +35,8 @@

Have an recipe idea for the cookbook? Contribute your ideas on GitHub!

-

Dealing With Accessibility Font Sizes in React Native

Modern phones have a lot of accessibility options. Users can make the font size on Android GIGANTIC. This is a way you can allow users to scale their fonts larger and smaller, but only to a certain point. We wanted the accessibility but not the extreme ends of it, just to keep things readable without turning off font scaling completely.

import * as React from "react";
import { View, TextProps, PixelRatio, AppState } from "react-native";
import { MaterialTopTabNavigationOptions } from "@react-navigation/material-top-tabs";
import { StackNavigationOptions } from "@react-navigation/stack";
import { BottomTabNavigationOptions } from "@react-navigation/bottom-tabs";
import { DrawerNavigationOptions } from "@react-navigation/drawer";
import { Text } from "./Text";

// These constants determine how much bigger the font size should get based on the user's
// accessibility settings. Even if they turn the dial all the way to 11, we will only ever
// scale the fonts by these factors. This is to prevent the font size from getting too large
// and completely breaking the layout.
const MAX_FONT_SCALE = 1.2;
const MIN_FONT_SCALE = 0.8;

// Returns fontScaling props for Text and TextInput components
// Usage:
// const fontProps = useFontScaling();
// return <Text {...fontProps}>Text Here</Text>;
export const useFontScaling = (): Partial<TextProps> => {
// You probably want to get this value from your user's preferences
const [allowFontScaling,] = React.useState(true);

const fontScaling: Partial<TextProps> = React.useMemo(() => {
return {
minimumFontScale: allowFontScaling ? MIN_FONT_SCALE : 1, // This prevents the font from getting too small.
maxFontSizeMultiplier: allowFontScaling ? MAX_FONT_SCALE : 1, // This prevents the font from getting too big.
allowFontScaling, // This allows the font to be scaled or not.
};
}, [allowFontScaling]);

return fontScaling;
};

// Returns fontScaling props for Navigator components
export const useNavigatorFontScalingScreenOptions =
(): Partial<StackNavigationOptions> => {
// You probably want to get this value from your user's preferences
const [allowFontScaling,] = React.useState(true);

const fontScaling: Partial<StackNavigationOptions> = React.useMemo(() => {
return {
headerBackAllowFontScaling: allowFontScaling,
headerTitleAllowFontScaling: allowFontScaling,
};
}, [allowFontScaling]);

return fontScaling;
};

// Returns fontScaling props for Top Tab Navigator components
export const useTopTabNavigatorFontScalingScreenOptions =
(): Partial<MaterialTopTabNavigationOptions> => {
// You probably want to get this value from your user's preferences
const [allowFontScaling,] = React.useState(true);

const fontScaling: Partial<MaterialTopTabNavigationOptions> =
React.useMemo(() => {
return {
tabBarAllowFontScaling: allowFontScaling,
};
}, [allowFontScaling]);

return fontScaling;
};

// Returns fontScaling props for Tab Navigator components
export const useTabNavigatorFontScalingScreenOptions =
(): Partial<BottomTabNavigationOptions> => {
// You probably want to get this value from your user's preferences
const [allowFontScaling,] = React.useState(true);

const fontScaling: Partial<BottomTabNavigationOptions> =
React.useMemo(() => {
return {
tabBarAllowFontScaling: fontScaling,
headerTitleAllowFontScaling: fontScaling,
};
}, [allowFontScaling]);

return fontScaling;
};

// Returns fontScaling props for Tab Navigator components
export const useDrawerNavigatorFontScalingScreenOptions =
(): Partial<DrawerNavigationOptions> => {
const [allowFontScaling,] = React.useState(true);

const fontScaling: Partial<DrawerNavigationOptions> = React.useMemo(() => {
return {
drawerAllowFontScaling: allowFontScaling,
headerTitleAllowFontScaling: allowFontScaling,
};
}, [allowFontScaling]);

return fontScaling;
};

// Use this handy __DEV__ mode only component to figure out what the font size is actually doing.
export const DevFontSize = () => {
const [allowFontScaling,] = React.useState(true);
const [appStateVisible, setAppStateVisible] = React.useState(
AppState.currentState
);

React.useEffect(() => {
const subscription = AppState.addEventListener("change", (nextAppState) => {
setAppStateVisible(nextAppState);
});

return () => subscription.remove();
}, []);

// This memo has to listen to appStateVisible even though it's not a direct dependency
// so that we can reload the font size when the app switches back from user settings.
const fontSize = React.useMemo(() => {
if (allowFontScaling) {
return Math.min(
Math.max(PixelRatio.getFontScale(), MIN_FONT_SCALE),
MAX_FONT_SCALE
);
} else {
return 1.0;
}
}, [allowFontScaling, appStateVisible]); // eslint-disable-line react-hooks/exhaustive-deps

return __DEV__ ? (
<View style={{
backgroundColor: '#E58F83',
padding: 10,
margin: 10,
borderRadius: 5,
borderColor: '#000,
borderWidth: 1,
}}>
<Text>
User Font Setting: {Math.trunc(PixelRatio.getFontScale() * 100) / 100}
</Text>
<Text>
Currently limiting ratio to: {Math.trunc(fontSize * 100) / 100}
</Text>
</View>
) : null;
};

Is this page still up to date? Did it work for you?

- - +

Dealing With Accessibility Font Sizes in React Native

Modern phones have a lot of accessibility options. Users can make the font size on Android GIGANTIC. This is a way you can allow users to scale their fonts larger and smaller, but only to a certain point. We wanted the accessibility but not the extreme ends of it, just to keep things readable without turning off font scaling completely.

import * as React from "react";
import { View, TextProps, PixelRatio, AppState } from "react-native";
import { MaterialTopTabNavigationOptions } from "@react-navigation/material-top-tabs";
import { StackNavigationOptions } from "@react-navigation/stack";
import { BottomTabNavigationOptions } from "@react-navigation/bottom-tabs";
import { DrawerNavigationOptions } from "@react-navigation/drawer";
import { Text } from "./Text";

// These constants determine how much bigger the font size should get based on the user's
// accessibility settings. Even if they turn the dial all the way to 11, we will only ever
// scale the fonts by these factors. This is to prevent the font size from getting too large
// and completely breaking the layout.
const MAX_FONT_SCALE = 1.2;
const MIN_FONT_SCALE = 0.8;

// Returns fontScaling props for Text and TextInput components
// Usage:
// const fontProps = useFontScaling();
// return <Text {...fontProps}>Text Here</Text>;
export const useFontScaling = (): Partial<TextProps> => {
// You probably want to get this value from your user's preferences
const [allowFontScaling,] = React.useState(true);

const fontScaling: Partial<TextProps> = React.useMemo(() => {
return {
minimumFontScale: allowFontScaling ? MIN_FONT_SCALE : 1, // This prevents the font from getting too small.
maxFontSizeMultiplier: allowFontScaling ? MAX_FONT_SCALE : 1, // This prevents the font from getting too big.
allowFontScaling, // This allows the font to be scaled or not.
};
}, [allowFontScaling]);

return fontScaling;
};

// Returns fontScaling props for Navigator components
export const useNavigatorFontScalingScreenOptions =
(): Partial<StackNavigationOptions> => {
// You probably want to get this value from your user's preferences
const [allowFontScaling,] = React.useState(true);

const fontScaling: Partial<StackNavigationOptions> = React.useMemo(() => {
return {
headerBackAllowFontScaling: allowFontScaling,
headerTitleAllowFontScaling: allowFontScaling,
};
}, [allowFontScaling]);

return fontScaling;
};

// Returns fontScaling props for Top Tab Navigator components
export const useTopTabNavigatorFontScalingScreenOptions =
(): Partial<MaterialTopTabNavigationOptions> => {
// You probably want to get this value from your user's preferences
const [allowFontScaling,] = React.useState(true);

const fontScaling: Partial<MaterialTopTabNavigationOptions> =
React.useMemo(() => {
return {
tabBarAllowFontScaling: allowFontScaling,
};
}, [allowFontScaling]);

return fontScaling;
};

// Returns fontScaling props for Tab Navigator components
export const useTabNavigatorFontScalingScreenOptions =
(): Partial<BottomTabNavigationOptions> => {
// You probably want to get this value from your user's preferences
const [allowFontScaling,] = React.useState(true);

const fontScaling: Partial<BottomTabNavigationOptions> =
React.useMemo(() => {
return {
tabBarAllowFontScaling: fontScaling,
headerTitleAllowFontScaling: fontScaling,
};
}, [allowFontScaling]);

return fontScaling;
};

// Returns fontScaling props for Tab Navigator components
export const useDrawerNavigatorFontScalingScreenOptions =
(): Partial<DrawerNavigationOptions> => {
const [allowFontScaling,] = React.useState(true);

const fontScaling: Partial<DrawerNavigationOptions> = React.useMemo(() => {
return {
drawerAllowFontScaling: allowFontScaling,
headerTitleAllowFontScaling: allowFontScaling,
};
}, [allowFontScaling]);

return fontScaling;
};

// Use this handy __DEV__ mode only component to figure out what the font size is actually doing.
export const DevFontSize = () => {
const [allowFontScaling,] = React.useState(true);
const [appStateVisible, setAppStateVisible] = React.useState(
AppState.currentState
);

React.useEffect(() => {
const subscription = AppState.addEventListener("change", (nextAppState) => {
setAppStateVisible(nextAppState);
});

return () => subscription.remove();
}, []);

// This memo has to listen to appStateVisible even though it's not a direct dependency
// so that we can reload the font size when the app switches back from user settings.
const fontSize = React.useMemo(() => {
if (allowFontScaling) {
return Math.min(
Math.max(PixelRatio.getFontScale(), MIN_FONT_SCALE),
MAX_FONT_SCALE
);
} else {
return 1.0;
}
}, [allowFontScaling, appStateVisible]); // eslint-disable-line react-hooks/exhaustive-deps

return __DEV__ ? (
<View style={{
backgroundColor: '#E58F83',
padding: 10,
margin: 10,
borderRadius: 5,
borderColor: '#000,
borderWidth: 1,
}}>
<Text>
User Font Setting: {Math.trunc(PixelRatio.getFontScale() * 100) / 100}
</Text>
<Text>
Currently limiting ratio to: {Math.trunc(fontSize * 100) / 100}
</Text>
</View>
) : null;
};

Is this page still up to date? Did it work for you?

+ + \ No newline at end of file diff --git a/docs/recipes/CircleCIRNSetup/index.html b/docs/recipes/CircleCIRNSetup/index.html index d44b91b1..577a41ee 100644 --- a/docs/recipes/CircleCIRNSetup/index.html +++ b/docs/recipes/CircleCIRNSetup/index.html @@ -8,8 +8,8 @@ CircleCI CD Setup - React Native | Ignite Cookbook for React Native - - + +
@@ -35,11 +35,11 @@

Have an recipe idea for the cookbook? Contribute your ideas on GitHub!

-

CircleCI CD Setup - React Native

This document shows the steps necessary to set up CircleCI automatic continuous integration testing and automatic Fastlane beta builds upon successfully merging a pull request.

First Things First

  1. Write Tests
  • If the project already has tests, great. If not, write some.
  • See this for an example of how Infinite Red typically sets up tests for a React Native app.

CircleCI Setup

  1. Log into CircleCI with your Github account
  2. Choose your organization from the dropdown in the top left
  3. Navigate to Add Projects on the left
  4. Search for your repo
  5. Choose Set Up Project
  6. Set Up Project
  • Select macOS for the operating system and Other for the language
  1. Copy the basic config.yml to .circleci/config.yml, commit your code changes and push to github master
  2. Choose Start building to initiate the first CI build. This build will fail. That's ok. We will update the config in the next step.
  3. Enable builds from forked pull requests. Go to project settings > Advanced Settings, then toggle on Build forked pull requests
  4. If this project is open-source, you'll want to make sure the open-source setting is enabled to allow for macOS builds. Go to project settings > Advanced Settings, then toggle Free and Open Source.

Continuous Integration

  1. Create a folder in the project root named .circleci.
  2. Create a file inside that folder named config.yml
  3. Use the below template in that file.
  4. If needed, see configuration docs for additional configuration options. (Here is a complete config.yml with CI and CD steps completed)
defaults: &defaults
docker:
# Choose the version of Node you want here
- image: circleci/node:10.11
working_directory: ~/repo

version: 2
jobs:
setup:
<<: *defaults
steps:
- checkout
- restore_cache:
keys:
- v1-dependencies-node-{{ checksum "package.json" }}
# fallback to using the latest cache if no exact match is found
- v1-dependencies-node-
- run:
name: Install dependencies
command: yarn install
- save_cache:
name: Save node modules
paths:
- node_modules
key: v1-dependencies-node-{{ checksum "package.json" }}

tests:
<<: *defaults
steps:
- checkout
- restore_cache:
keys:
- v1-dependencies-node-{{ checksum "package.json" }}
# fallback to using the latest cache if no exact match is found
- v1-dependencies-node-
- run:
name: Run tests
command: yarn ci:test # this command will be added to/found in your package.json scripts

workflows:
version: 2
test_and_release:
jobs:
- setup
- tests:
requires:
- setup
  1. Make sure the test script is added to your package.json
  {
...
"scripts": {
...
"ci:test": "<command to run tests>" <<-- if you don't already have this one
},
...
}

iOS Continuous Deployment

Add Fastlane

  1. Before you can add continuous deployment, you'll need to setup Fastlane and Match to sign and deploy your app. You can follow these blog posts to get setup!
  1. In your Fastfile, add:
before_all do
setup_circle_ci
end
  1. In your beta lane, make sure you have included a command that bumps the build number prior to building, and then commits the build number after building. +

CircleCI CD Setup - React Native

This document shows the steps necessary to set up CircleCI automatic continuous integration testing and automatic Fastlane beta builds upon successfully merging a pull request.

First Things First

  1. Write Tests
  • If the project already has tests, great. If not, write some.
  • See this for an example of how Infinite Red typically sets up tests for a React Native app.

CircleCI Setup

  1. Log into CircleCI with your Github account
  2. Choose your organization from the dropdown in the top left
  3. Navigate to Add Projects on the left
  4. Search for your repo
  5. Choose Set Up Project
  6. Set Up Project
  • Select macOS for the operating system and Other for the language
  1. Copy the basic config.yml to .circleci/config.yml, commit your code changes and push to github master
  2. Choose Start building to initiate the first CI build. This build will fail. That's ok. We will update the config in the next step.
  3. Enable builds from forked pull requests. Go to project settings > Advanced Settings, then toggle on Build forked pull requests
  4. If this project is open-source, you'll want to make sure the open-source setting is enabled to allow for macOS builds. Go to project settings > Advanced Settings, then toggle Free and Open Source.

Continuous Integration

  1. Create a folder in the project root named .circleci.
  2. Create a file inside that folder named config.yml
  3. Use the below template in that file.
  4. If needed, see configuration docs for additional configuration options. (Here is a complete config.yml with CI and CD steps completed)
defaults: &defaults
docker:
# Choose the version of Node you want here
- image: circleci/node:10.11
working_directory: ~/repo

version: 2
jobs:
setup:
<<: *defaults
steps:
- checkout
- restore_cache:
keys:
- v1-dependencies-node-{{ checksum "package.json" }}
# fallback to using the latest cache if no exact match is found
- v1-dependencies-node-
- run:
name: Install dependencies
command: yarn install
- save_cache:
name: Save node modules
paths:
- node_modules
key: v1-dependencies-node-{{ checksum "package.json" }}

tests:
<<: *defaults
steps:
- checkout
- restore_cache:
keys:
- v1-dependencies-node-{{ checksum "package.json" }}
# fallback to using the latest cache if no exact match is found
- v1-dependencies-node-
- run:
name: Run tests
command: yarn ci:test # this command will be added to/found in your package.json scripts

workflows:
version: 2
test_and_release:
jobs:
- setup
- tests:
requires:
- setup
  1. Make sure the test script is added to your package.json
  {
...
"scripts": {
...
"ci:test": "<command to run tests>" <<-- if you don't already have this one
},
...
}

iOS Continuous Deployment

Add Fastlane

  1. Before you can add continuous deployment, you'll need to setup Fastlane and Match to sign and deploy your app. You can follow these blog posts to get setup!
  1. In your Fastfile, add:
before_all do
setup_circle_ci
end
  1. In your beta lane, make sure you have included a command that bumps the build number prior to building, and then commits the build number after building. Example:
PROJECT = "YourProject"
XCODE_PROJECT = "#{PROJECT}.xcodeproj"
lane :beta do
increment_build_number(xcodeproj: "./#{XCODE_PROJECT}")
match(type: "appstore")
build_ios_app(
scheme: PROJECT,
workspace: "./YourProject.xcworkspace",
xcargs: "-UseNewBuildSystem=NO -allowProvisioningUpdates",
export_method: "app-store"
)
# Ship it!
upload_to_testflight(
skip_waiting_for_build_processing: true
)
commit_version_bump(
xcodeproj: "./#{XCODE_PROJECT}",
ignore: /tvOS/,
force: true,
message: "[skip ci] Version bump"
)
end
  1. If you prefer, you can also do these steps as separate fastlane commands, just make sure to include a - run: entry for each one in config.yml.

Setting up CircleCI to Run Fastlane Check out this blog post for lots of helpful tips.

  1. Make sure CircleCI has all the credentials to run your fastlane scripts:
    • Go into the Settings screen for your project on CircleCI
    • Under "Build Settings", click on "Environment Variables" (https://circleci.com/gh/YOUR_ORG/YOURPROJECT/edit#env-vars)
    • Click "Add Variable"
    • Set FASTLANE_USER to the email address of your your Apple App Store Connect / Dev Portal user.
    • Do this for all of the variables listed here Note: If your dev portal user does not have 2-Factor Auth turned on, you DO NOT need to set FASTLANE_APPLE_APPLICATION_SPECIFIC_PASSWORD. Including this variable when your account does need it will result in errors during TestFlight upload. You can find more info from the Fastlane Docs, and from the CircleCI codesigning docs
  2. Add GITHUB_TOKEN to env vars on CircleCI (https://circleci.com/gh/YOUR_ORG/YOURPROJECT/edit#env-vars). Y
  1. Add the Circle CI Github team to your repo (https://github.com/YOUR_ORG/YOURPROJECT/settings/collaboration) with write access.
  2. Add the Circle CI Github team as a read-only collaborator to the private match certificates repo.
  3. Log in to GitHub/CircleCI as the CI user. Then in CircleCI, go to Project Settings > Checkout SSH keys (https://circleci.com/gh/YOURORGANIZATION/YOURPROJECT/edit#checkout) and add a new user key. This will allow CircleCI to clone the certs repo in order to sign your app.
  4. Go to Project Settings > Checkout SSH Keys and add a new deploy key. You will copy the fingerprint and paste into the config.yml example below in the add_ssh_keys section (there should be "s around it)
  5. Add a script to your package.json called ci:setup. This will run any necessary shell commands to prepare your project for building. For example, creating private files like .env. If you don't any additional setup, you can leave this command as "", or remove the ci:setup step from the config.yml example below.
  {
...
"scripts": {
...
"ci:setup": "touch .env && echo \"ENV_VAR=\"$ENV_VAR >> .env",
},
...
}

Note: react-native-dotenv throws errors if there is not a .env present with the variables it expects. However, if you don't want to put secret values in this script (you shouldn't), then you can add them directly to CircleCI under Project Settings > Environment Variables. Then you can reference them in this script as $ENV_VAR.

  1. Add mac configuration and deploy_ios job to your CircleCI config.yml NOTE: The macOS boxes currently come with Node 11.0, with no apparent way to change the version. This shouldn't be a huge problem. One known issue is with upath, which is a deep dependency of react-native. If you encounter errors related to upath requiring a lower version of Node, just make sure it is at 1.1.0, and not 1.0.4 in your yarn.lock. See https://github.com/airbnb/enzyme/issues/1637#issuecomment-397327562.
defaults: ...

mac: &mac
macos:
xcode: "10.1.0"
working_directory: ~/repo
environment:
FL_OUTPUT_DIR: output
shell: /bin/bash --login -o pipefail

version: 2
jobs:
setup: ...

tests: ...

deploy_ios:
<<: *mac
steps:
- checkout
- add_ssh_keys:
fingerprints: — “SSH_FINGERPRINT_HERE”
- run:
name: Git configuration
command: git config user.email "ci@your.domain" && git config user.name "CircleCI"
- run:
name: Set upstream branch
command: git branch --set-upstream-to origin ${CIRCLE_BRANCH}
# Node modules
- restore_cache:
name: Restore node modules
keys:
- v1-dependencies-mac-{{ checksum "package.json" }}
# fallback to using the latest cache if no exact match is found
- v1-dependencies-mac-
- run:
name: Install dependencies
command: NOYARNPOSTINSTALL=1 yarn install
- save_cache:
name: Save node modules
paths:
- node_modules
key: v1-dependencies-mac-{{ checksum "package.json" }}

# Cocoapods
- run:
name: Fetch CocoaPods Specs
command: |
curl https://cocoapods-specs.circleci.com/fetch-cocoapods-repo-from-s3.sh | bash -s cf
- run:
working_directory: ios
name: Install CocoaPods
command: pod install --verbose

# Gems
- restore_cache:
name: Restore gems
key: bundle-v1-{{ checksum "ios/Gemfile.lock" }}-{{ arch }}
- run:
name: Bundle Install
command: bundle install
working_directory: ios
- save_cache:
key: bundle-v1-{{ checksum "ios/Gemfile.lock" }}-{{ arch }}
paths:
- vendor/bundle

# Misc setup
- run:
name: Misc setup
command: yarn ci:setup

# Git grooming
- run:
name: Pull latest git
command: git stash && git pull && git stash pop

# Run Fastlane
- run:
working_directory: ios
name: Fastlane
command: bundle exec fastlane ios beta

# Git cleanup
- run:
name: Pull latest git
command: git stash && git pull && git stash pop
- run:
name: Push version bump commit
command: git push
- store_artifacts:
path: output

workflows:
version: 2
test_and_release:
jobs:
- setup
- tests:
requires:
- setup
- deploy_ios:
filters:
branches:
only: master
```

Troubleshooting tips

  • If you need to debug failed builds, you can use the "Rebuild with SSH" option in CircleCI. See https://circleci.com/docs/2.0/ssh-access-jobs/ for more info.
  • Tip: make sure you are logged in to Github/CircleCI as yourself (not the CI user) when you hit the button to rebuild with SSH.
  • If you get a vague error saying File main.jsbundle does not exist, that means there was an error while building the app and you can view the more detailed message by inspecting the log files with the following command (while in SSH mode). Increase the number of lines from 50 as needed.
  • tail -50 ios/output/buildlogs/gym/YourProject-YourProject.log

Is this page still up to date? Did it work for you?

- - + + \ No newline at end of file diff --git a/docs/recipes/CreatingGreateExperienceForScreenReaders/index.html b/docs/recipes/CreatingGreateExperienceForScreenReaders/index.html index 858ba41e..7a30be13 100644 --- a/docs/recipes/CreatingGreateExperienceForScreenReaders/index.html +++ b/docs/recipes/CreatingGreateExperienceForScreenReaders/index.html @@ -8,8 +8,8 @@ Creating a Good Experience for Screen Readers | Ignite Cookbook for React Native - - + +
@@ -35,7 +35,7 @@

Have an recipe idea for the cookbook? Contribute your ideas on GitHub!

-

Creating a Good Experience for Screen Readers

UI Patterns

Screens

Titles +

Creating a Good Experience for Screen Readers

UI Patterns

Screens

Titles All screen should ideally have unique titles, to make it easier to know quickly which screen you're on source.

Headings Apps should ideally mark headings to allow for quick "scanning" of the structure of screens (source). In React Native, mark headings with the "header" accessibility role.

Try to group controls as much as possible (source)

It is easier and quicker for people using a keyboard or screen reader to interact with content when not overwhelmed and confused by extraneous elements. Grouping elements into a single overall control makes things clearer, simplifies interactions, and can provide larger touch targets. @@ -43,7 +43,7 @@ Infinite scroll causes two main problems for screen readers: 1) there's no clear "end" to jump to, and 2) elements pop in, which need to be announced if there weren't there when the end was reached.

Toast, Dialog, or Modal Depending on the implementation used, these elements may not "announce" when they pop in. Evaluate solution for this before going with a library.

RN-specific issues

Test links nested in text with formatting Text links nested in other text elements aren't accessible. If you need to implement that design, there are a few options:

  • Wrap the parent text in a View and add custom accessibilityActions for opening the links
    • Do not apply custom accessibilityActions to text, those will cause a crash on iOS
  • Re-structure the component based on whether a screen reader is turned on (as in this blog post)

Labeling

A good accessibility label for an element is concise, but also unique and makes sense even when the screen is not read linearly. This is because one way to navigate with a screen reader is to search for a label. Another is to jump between controls (e.g., links, buttons, form fields), so if a header preceding a link is the only way to understand the link, it won't make sense in this navigation method.

See this post for some great advice on when and how to use labels: https://mobilea11y.com/blog/when-to-use-accessibility-labels

Is this page still up to date? Did it work for you?

- - + + \ No newline at end of file diff --git a/docs/recipes/DetoxIntro/index.html b/docs/recipes/DetoxIntro/index.html index 2aec5cee..8b9a4c2c 100644 --- a/docs/recipes/DetoxIntro/index.html +++ b/docs/recipes/DetoxIntro/index.html @@ -8,8 +8,8 @@ Detox Intro | Ignite Cookbook for React Native - - + +
@@ -35,8 +35,8 @@

Have an recipe idea for the cookbook? Contribute your ideas on GitHub!

-

Detox Intro

Detox is a library for end-to-end testing of React Native apps. This wiki provides information on how to use Detox effectively.

Installation

Detox's documentation for installation.

It's included by default in Ignite.

What's unique about Detox

Synchronization

One of the key features that makes Detox unique is that it synchronizes with app state, so it can know when to move to the next step of a test, instead of including manual sleep statements. See the documentation for more info.

But this does create new kinds of errors to be aware of. For example, if you see a Detox test hanging, that's an indication that Detox might not be detecting that the app went into the idle state so that the test can continue. To debug, check out Detox's troubleshooting guide on sync issues.

Flaky Tests

The RNR team interviewed Rotem Meidan, former lead of Detox, about Detox stability, in React-Native Radio 189.

He wrote an article about that here: Detox: Writing Stable Test Suites

Is this page still up to date? Did it work for you?

- - +

Detox Intro

Detox is a library for end-to-end testing of React Native apps. This wiki provides information on how to use Detox effectively.

Installation

Detox's documentation for installation.

It's included by default in Ignite.

What's unique about Detox

Synchronization

One of the key features that makes Detox unique is that it synchronizes with app state, so it can know when to move to the next step of a test, instead of including manual sleep statements. See the documentation for more info.

But this does create new kinds of errors to be aware of. For example, if you see a Detox test hanging, that's an indication that Detox might not be detecting that the app went into the idle state so that the test can continue. To debug, check out Detox's troubleshooting guide on sync issues.

Flaky Tests

The RNR team interviewed Rotem Meidan, former lead of Detox, about Detox stability, in React-Native Radio 189.

He wrote an article about that here: Detox: Writing Stable Test Suites

Is this page still up to date? Did it work for you?

+ + \ No newline at end of file diff --git a/docs/recipes/DistributingAuthTokenToAPI/index.html b/docs/recipes/DistributingAuthTokenToAPI/index.html index daa7db04..e1895a28 100644 --- a/docs/recipes/DistributingAuthTokenToAPI/index.html +++ b/docs/recipes/DistributingAuthTokenToAPI/index.html @@ -8,8 +8,8 @@ Distributing Auth Token to APIs | Ignite Cookbook for React Native - - + +
@@ -35,8 +35,8 @@

Have an recipe idea for the cookbook? Contribute your ideas on GitHub!

-

Distributing Auth Token to APISauce

Building off of the Ignite Boilerplate, this recipe will show you how to connect your Mobx State Tree Authentication Store with an Apisauce instance to make authenticating your API requests a breeze.

Review of API Instance and Auth Store

To start off let's quickly review the boilerplate Auth Store and API Instance.

In app/services/api/api.ts we have an example API class with an export of a singleton instance of that class at the end of the file. This api singleton is what we're going to use to update the apisauce configuration on the instance outside of this file.

export const DEFAULT_API_CONFIG: ApiConfig = {
url: Config.API_URL,
timeout: 10000,
}


export class Api {
apisauce: ApisauceInstance
config: ApiConfig

constructor(config: ApiConfig = DEFAULT_API_CONFIG) {
this.config = config
this.apisauce = create({
baseURL: this.config.url,
timeout: this.config.timeout,
headers: {
Accept: "application/json",
},
})
}

async getEpisodes(): Promise<{ kind: "ok"; episodes: EpisodeSnapshotIn[] } | GeneralApiProblem> {
... // example API call that needs authenticating
}

}

// Singleton instance of the API for convenience
export const api = new Api()

Next in app/models/AuthenticationStore.ts we have an action to set the auth token in the store after retrieving it.

import { Instance, SnapshotOut, types } from "mobx-state-tree";

export const AuthenticationStoreModel = types
.model("AuthenticationStore")
.props({
authToken: types.maybe(types.string),
authEmail: "",
})
.views((store) => ({}))
.actions((store) => ({
setAuthToken(value?: string) {
store.authToken = value;
},
}));

export interface AuthenticationStore
extends Instance<typeof AuthenticationStoreModel> {}
export interface AuthenticationStoreSnapshot
extends SnapshotOut<typeof AuthenticationStoreModel> {}

Distributing Auth Token to API Instance

Once we have an auth token and setAuthToken has been called, we need to hydrate the authentication header on all APIs that require requests to be authenticated. One of the easiest ways to do that is to grab the instance(s) in an action on the authStore and update the apiSauce configuration directly like so:

    // We will need to import the api from the service
import { api } from "app/services/api"

...

// then update the Authentication Model actions
.actions((store) => ({
setAuthToken(value?: string) {
store.authToken = value;
},
distributeAuthToken(value?: string) {
// optionally grab the store's authToken if not passing a value
const token = value || store.authToken;
api.apiSauce.setHeader("Authorization", `Bearer ${token}`);
},
})

From there you have a couple options of where to trigger the distribution.

  • Add another action that calls both setAuthToken and distributeAuthToken and replace wherever you call setAuthToken with this new dual action
  • Call distributeAuthToken immediately after wherever you are calling setAuthToken
  • Add the distributeAuthToken call to the setAuthToken action (not recommended because it doesn't follow the SRP of the action)

For example in app/screens/LoginScreen.tsx we can update the login function to distribute the auth token after setting it in the store.

    // We can update `authenticationStore` from the useStores hook to include `distributeAuthToken`
const {
authenticationStore: { authEmail, setAuthEmail, setAuthToken, distributeAuthToken, validationError },
} = useStores()

...

function login() {
setIsSubmitted(true);
setAttemptsCount(attemptsCount + 1);

if (validationError) return;

// Make a request to your server to get an authentication token.
// If successful, reset the fields and set the token.
setIsSubmitted(false);
setAuthPassword("");
setAuthEmail("");

// We'll mock this with a fake token.
const token = String(Date.now());
setAuthToken(token);
distributeAuthToken(token);
}

And that's it! Now all of your requests made using that API will include the authentication header, leveraging the auth token received on login.

Other configuration

This method works for updating both the apisauce and config properties on the default API instance or any custom properties you have added to the API!

Is this page still up to date? Did it work for you?

- - +

Distributing Auth Token to APISauce

Building off of the Ignite Boilerplate, this recipe will show you how to connect your Mobx State Tree Authentication Store with an Apisauce instance to make authenticating your API requests a breeze.

Review of API Instance and Auth Store

To start off let's quickly review the boilerplate Auth Store and API Instance.

In app/services/api/api.ts we have an example API class with an export of a singleton instance of that class at the end of the file. This api singleton is what we're going to use to update the apisauce configuration on the instance outside of this file.

export const DEFAULT_API_CONFIG: ApiConfig = {
url: Config.API_URL,
timeout: 10000,
}


export class Api {
apisauce: ApisauceInstance
config: ApiConfig

constructor(config: ApiConfig = DEFAULT_API_CONFIG) {
this.config = config
this.apisauce = create({
baseURL: this.config.url,
timeout: this.config.timeout,
headers: {
Accept: "application/json",
},
})
}

async getEpisodes(): Promise<{ kind: "ok"; episodes: EpisodeSnapshotIn[] } | GeneralApiProblem> {
... // example API call that needs authenticating
}

}

// Singleton instance of the API for convenience
export const api = new Api()

Next in app/models/AuthenticationStore.ts we have an action to set the auth token in the store after retrieving it.

import { Instance, SnapshotOut, types } from "mobx-state-tree";

export const AuthenticationStoreModel = types
.model("AuthenticationStore")
.props({
authToken: types.maybe(types.string),
authEmail: "",
})
.views((store) => ({}))
.actions((store) => ({
setAuthToken(value?: string) {
store.authToken = value;
},
}));

export interface AuthenticationStore
extends Instance<typeof AuthenticationStoreModel> {}
export interface AuthenticationStoreSnapshot
extends SnapshotOut<typeof AuthenticationStoreModel> {}

Distributing Auth Token to API Instance

Once we have an auth token and setAuthToken has been called, we need to hydrate the authentication header on all APIs that require requests to be authenticated. One of the easiest ways to do that is to grab the instance(s) in an action on the authStore and update the apiSauce configuration directly like so:

    // We will need to import the api from the service
import { api } from "app/services/api"

...

// then update the Authentication Model actions
.actions((store) => ({
setAuthToken(value?: string) {
store.authToken = value;
},
distributeAuthToken(value?: string) {
// optionally grab the store's authToken if not passing a value
const token = value || store.authToken;
api.apiSauce.setHeader("Authorization", `Bearer ${token}`);
},
})

From there you have a couple options of where to trigger the distribution.

  • Add another action that calls both setAuthToken and distributeAuthToken and replace wherever you call setAuthToken with this new dual action
  • Call distributeAuthToken immediately after wherever you are calling setAuthToken
  • Add the distributeAuthToken call to the setAuthToken action (not recommended because it doesn't follow the SRP of the action)

For example in app/screens/LoginScreen.tsx we can update the login function to distribute the auth token after setting it in the store.

    // We can update `authenticationStore` from the useStores hook to include `distributeAuthToken`
const {
authenticationStore: { authEmail, setAuthEmail, setAuthToken, distributeAuthToken, validationError },
} = useStores()

...

function login() {
setIsSubmitted(true);
setAttemptsCount(attemptsCount + 1);

if (validationError) return;

// Make a request to your server to get an authentication token.
// If successful, reset the fields and set the token.
setIsSubmitted(false);
setAuthPassword("");
setAuthEmail("");

// We'll mock this with a fake token.
const token = String(Date.now());
setAuthToken(token);
distributeAuthToken(token);
}

And that's it! Now all of your requests made using that API will include the authentication header, leveraging the auth token received on login.

Other configuration

This method works for updating both the apisauce and config properties on the default API instance or any custom properties you have added to the API!

Is this page still up to date? Did it work for you?

+ + \ No newline at end of file diff --git a/docs/recipes/EASUpdate/index.html b/docs/recipes/EASUpdate/index.html index 1c4441ec..8409e87c 100644 --- a/docs/recipes/EASUpdate/index.html +++ b/docs/recipes/EASUpdate/index.html @@ -8,8 +8,8 @@ EAS Update | Ignite Cookbook for React Native - - + +
@@ -35,8 +35,8 @@

Have an recipe idea for the cookbook? Contribute your ideas on GitHub!

-

EAS Update

This guide will teach you how to set up over-the-air (OTA) updates with Expo and EAS Update within an Ignite project.

Appetizer

Follow the Pristine Expo Project recipe first to make sure you're starting with an Expo only project.

You'll also need eas-cli globally installed and and an Expo account if you don't already have one.

npm install -g eas-cli

Steps

1. Project Setup

From within your project directory, run the following:

npx expo install expo-updates
eas build:configure
  • Answer yes to setting up the EAS project prompt and you can configure it for both platforms (note: for the purposes of this guide we'll be using Android)
  • This will make some edits to your app.json now that the project has an EAS identifier, as well as add a new eas.json configuration file.
eas update:configure
  • Some more app.json changes will be made adding an updates key to your configuration file.

2. Edit Build Profiles

Modify the newly generated eas.json to configure a preview build profile. We'll be using a buildType of apk for the Android build to keep things easy for testing, your production build can still use an Android App Bundle.

{
"cli": {
"version": ">= 3.0.0"
},
"build": {
"development": {
"developmentClient": true,
"distribution": "internal"
},
"preview": {
"channel": "preview",
"android": { "buildType": "apk" },
"ios": { "simulator": false }
},
"production": {}
},
"submit": {
"production": {}
}
}

3. Create the Build

Next, we'll create a build that we can test with on either an Android emulator or device. You may do this via EAS or locally if you the added queue time for an unpaid EAS account is getting in your way.

# via EAS
eas build --profile preview -p android

# locally
eas build --profile preview -p android --local

Accept the prompts for generating the new Android Keystore. Once that is completed (~7-10 minutes if you do it locally, add some extra time if using the EAS servers due to the queue time), drop it on your emulator or device and fire it up! 🔥

4. Making a Project Update

Right now you should be staring at the <LoginScreen /> of the Ignite demo code. Let's go ahead and make an update to that so we can deploy it OTA. Open up ./app/screens/LoginScreen.tsx. Feel free to make any modification, but for an example, let's change the header text:

<Text testID="login-heading" tx="loginScreen.signIn" preset="heading" style={$signIn} />
<Text testID="login-heading" text="Welcome! Please sign in" preset="heading" style={$signIn} />

Observe that currently there are no changes to your application (as metro is not running), there are no hot reloads going on and the header text remains Sign in.

5. Publishing OTA

Create the Update Channel

To publish this out to our app which is living on the preview channel (via the build profile in eas.json), we'll set up the channel:

eas channel:create preview

This only has to be done once if the channel doesn't exist (which you can confirm via eas channel:view [name]).

Upload Changes to EAS

Next, tell EAS about the update package to send out with our new changes:

eas update --branch preview --message "update login screen"

Download the Updates OTA

Now that the updates are on the server, we can look to update our app on our emulator/device. If the app is still in the foreground, swipe the app away to close it.

Reopen it from the app drawer. At this point in time, the default Expo update flow is to check for new updates on the update channel (formerly release channel if you're coming over from expo publish). If there is a pending compatible update, it will now be downloaded.

Close the app again and reopen it. Now the update will actually be applied. Note the change in the heading at the top of the sign in screen. It should match Welcome! Please sign in or whatever modification you made in Step 4.

You've now successfully sent an update over-the-air! Waiting on the app store review has been skipped and your critical bug fix is out there to the masses.

Customized Update Flow

You'll note in Step 5 that it was kind of magical / lucky that we rebooted the app twice to get the update. This can be difficult to communicate that kind of behavior to users. You can build on the foundation from this guide and add a more customized approach, providing the user with a better experience in a few ways. Here is one example flow:

  1. Check for updates
  2. If one exists, alert the user
  3. Should they choose to update, keep them updated that it is in progress
  4. After successfully getting the update, offer to restart the app for the user
  5. On any errors, communicate that it could not be completed at this time.

To achieve this functionality, you'll have to make some modifications to the app.json for more manual control over the flow, in addition to your UI changes.

{
// ...
"updates": {
"checkAutomatically": "ON_ERROR_RECOVERY"
// ...
}
}

This will tell Expo to skip checking for updates on load and instead only do it when we request a check. Look into the following methods to achieve this:

Notes

Upgrading to the next Expo SDK version, native code changes and app.json or app.config.js changes behave differently, so make sure to read the additional documentation below if that is your goal.

More Resources

Is this page still up to date? Did it work for you?

- - +

EAS Update

This guide will teach you how to set up over-the-air (OTA) updates with Expo and EAS Update within an Ignite project.

Appetizer

Follow the Pristine Expo Project recipe first to make sure you're starting with an Expo only project.

You'll also need eas-cli globally installed and and an Expo account if you don't already have one.

npm install -g eas-cli

Steps

1. Project Setup

From within your project directory, run the following:

npx expo install expo-updates
eas build:configure
  • Answer yes to setting up the EAS project prompt and you can configure it for both platforms (note: for the purposes of this guide we'll be using Android)
  • This will make some edits to your app.json now that the project has an EAS identifier, as well as add a new eas.json configuration file.
eas update:configure
  • Some more app.json changes will be made adding an updates key to your configuration file.

2. Edit Build Profiles

Modify the newly generated eas.json to configure a preview build profile. We'll be using a buildType of apk for the Android build to keep things easy for testing, your production build can still use an Android App Bundle.

{
"cli": {
"version": ">= 3.0.0"
},
"build": {
"development": {
"developmentClient": true,
"distribution": "internal"
},
"preview": {
"channel": "preview",
"android": { "buildType": "apk" },
"ios": { "simulator": false }
},
"production": {}
},
"submit": {
"production": {}
}
}

3. Create the Build

Next, we'll create a build that we can test with on either an Android emulator or device. You may do this via EAS or locally if you the added queue time for an unpaid EAS account is getting in your way.

# via EAS
eas build --profile preview -p android

# locally
eas build --profile preview -p android --local

Accept the prompts for generating the new Android Keystore. Once that is completed (~7-10 minutes if you do it locally, add some extra time if using the EAS servers due to the queue time), drop it on your emulator or device and fire it up! 🔥

4. Making a Project Update

Right now you should be staring at the <LoginScreen /> of the Ignite demo code. Let's go ahead and make an update to that so we can deploy it OTA. Open up ./app/screens/LoginScreen.tsx. Feel free to make any modification, but for an example, let's change the header text:

<Text testID="login-heading" tx="loginScreen.signIn" preset="heading" style={$signIn} />
<Text testID="login-heading" text="Welcome! Please sign in" preset="heading" style={$signIn} />

Observe that currently there are no changes to your application (as metro is not running), there are no hot reloads going on and the header text remains Sign in.

5. Publishing OTA

Create the Update Channel

To publish this out to our app which is living on the preview channel (via the build profile in eas.json), we'll set up the channel:

eas channel:create preview

This only has to be done once if the channel doesn't exist (which you can confirm via eas channel:view [name]).

Upload Changes to EAS

Next, tell EAS about the update package to send out with our new changes:

eas update --branch preview --message "update login screen"

Download the Updates OTA

Now that the updates are on the server, we can look to update our app on our emulator/device. If the app is still in the foreground, swipe the app away to close it.

Reopen it from the app drawer. At this point in time, the default Expo update flow is to check for new updates on the update channel (formerly release channel if you're coming over from expo publish). If there is a pending compatible update, it will now be downloaded.

Close the app again and reopen it. Now the update will actually be applied. Note the change in the heading at the top of the sign in screen. It should match Welcome! Please sign in or whatever modification you made in Step 4.

You've now successfully sent an update over-the-air! Waiting on the app store review has been skipped and your critical bug fix is out there to the masses.

Customized Update Flow

You'll note in Step 5 that it was kind of magical / lucky that we rebooted the app twice to get the update. This can be difficult to communicate that kind of behavior to users. You can build on the foundation from this guide and add a more customized approach, providing the user with a better experience in a few ways. Here is one example flow:

  1. Check for updates
  2. If one exists, alert the user
  3. Should they choose to update, keep them updated that it is in progress
  4. After successfully getting the update, offer to restart the app for the user
  5. On any errors, communicate that it could not be completed at this time.

To achieve this functionality, you'll have to make some modifications to the app.json for more manual control over the flow, in addition to your UI changes.

{
// ...
"updates": {
"checkAutomatically": "ON_ERROR_RECOVERY"
// ...
}
}

This will tell Expo to skip checking for updates on load and instead only do it when we request a check. Look into the following methods to achieve this:

Notes

Upgrading to the next Expo SDK version, native code changes and app.json or app.config.js changes behave differently, so make sure to read the additional documentation below if that is your goal.

More Resources

Is this page still up to date? Did it work for you?

+ + \ No newline at end of file diff --git a/docs/recipes/EnvironmentVariables/index.html b/docs/recipes/EnvironmentVariables/index.html index d8680b7a..17fab949 100644 --- a/docs/recipes/EnvironmentVariables/index.html +++ b/docs/recipes/EnvironmentVariables/index.html @@ -8,8 +8,8 @@ Environment Variables | Ignite Cookbook for React Native - - + +
@@ -35,8 +35,8 @@

Have an recipe idea for the cookbook? Contribute your ideas on GitHub!

-

Environment Variables

Setup

Install

yarn add -D dotenv babel-plugin-inline-dotenv

Configure

Add inline-dotenv to your babel.config.js or .babelrc, for example:

// babel.config.js

const plugins = [
[
"@babel/plugin-proposal-decorators",
{
legacy: true,
},
],
["@babel/plugin-proposal-optional-catch-binding"],
"inline-dotenv",
"react-native-reanimated/plugin", // NOTE: this must be last in the plugins
];

const expoConfig = {
presets: ["babel-preset-expo"],
env: {
production: {},
},
plugins,
};

Note: this configuration also works for a bare react-native app

Usage

Create a .env file in the root of your project

MY_VAR="MY_VALUE"
KEEP_IN_MIND="THESE ARE NOT SECURE"

You'll now have access to your values from the .env file

console.log(process.env.MY_VAR); // results in: MY_VALUE
console.log(process.env.KEEP_IN_MIND); // results in: THESE ARE NOT SECURE

If making changes to the environment variables, you'll have to restart your metro server (and possibly clear cache)

Is this page still up to date? Did it work for you?

- - +

Environment Variables

Setup

Install

yarn add -D dotenv babel-plugin-inline-dotenv

Configure

Add inline-dotenv to your babel.config.js or .babelrc, for example:

// babel.config.js

const plugins = [
[
"@babel/plugin-proposal-decorators",
{
legacy: true,
},
],
["@babel/plugin-proposal-optional-catch-binding"],
"inline-dotenv",
"react-native-reanimated/plugin", // NOTE: this must be last in the plugins
];

const expoConfig = {
presets: ["babel-preset-expo"],
env: {
production: {},
},
plugins,
};

Note: this configuration also works for a bare react-native app

Usage

Create a .env file in the root of your project

MY_VAR="MY_VALUE"
KEEP_IN_MIND="THESE ARE NOT SECURE"

You'll now have access to your values from the .env file

console.log(process.env.MY_VAR); // results in: MY_VALUE
console.log(process.env.KEEP_IN_MIND); // results in: THESE ARE NOT SECURE

If making changes to the environment variables, you'll have to restart your metro server (and possibly clear cache)

Is this page still up to date? Did it work for you?

+ + \ No newline at end of file diff --git a/docs/recipes/ExpoRouter/index.html b/docs/recipes/ExpoRouter/index.html new file mode 100644 index 00000000..cbbeff24 --- /dev/null +++ b/docs/recipes/ExpoRouter/index.html @@ -0,0 +1,44 @@ + + + + + + + + + +Expo Router | Ignite Cookbook for React Native + + + + +
+

Expo Router

Overview

Expo Router brings file-based routing to React Native and web applications allowing you to easily create universal apps. Whenever a file is added to your src/app directory, a new path is automatically added to your navigation.

For the full documentation by Expo, head on over to the Introduction to Expo Router.

Ignite v9 is fully equipped to utilize expo-router after dependency installation and some directory structure updates! In this recipe, we'll convert the demo app's auth and tab navigators from react-navigation to use expo-router.

Installation and Project Configuration

Bootstrap a new Ignite project:

npx ignite-cli@next new pizza-router --yes
cd pizza-router

Add the missing dependencies expo-router needs:

npx expo install expo-router expo-constants

Add expo-router to app.json plugins list if necessary:

"plugins": [
...
"expo-font",
"expo-router"
],

Change the entry point that expo-router expects in package.json:

"main": "node_modules/expo/AppEntry.js",
"main": "expo-router/entry",

expo-router has great TypeScript support, so let's enable that in app.json under experiments.

{
"expo": {
"experiments": {
"tsconfigPaths": true,
"typedRoutes": true
}
}
}

Reworking the Directory Structure

Expo Router requires route files to live in either app or src/app directories. But since our Ignite project is already using app, we'll need to rename it to src. We'll create src/app to contain all the file-base routing files from here on out, and models, components and other shared files will be located in the src directory now. We'll also remove App.tsx as this is no longer the entry point of the application.

rm App.tsx
mv app src
mkdir src/app

Let's update the TS alias and include paths over in tsconfig.json

{
"compilerOptions": {
// ...
"paths": {
"app/*": ["./app/*"],
"src/*": ["./src/*"],
// ...
},
}
"include": [
"index.js",
"App.tsx",
"app",
"types",
"plugins",
"app.config.ts",
".expo/types/**/*.ts",
"expo-env.d.ts"
],
"include": ["**/*.ts", "**/*.tsx"],
// ...
}

Fix Imports

We also need to fix up a few imports to use src/ instead of app/. +Ignite's Demo App only contains a few files we need to update, but an existing app could contain more.

package.json

"format": "prettier --write \"app/**/*.{js,jsx,json,md,ts,tsx}\"",
"lint": "eslint App.tsx app test --fix --ext .js,.ts,.tsx && npm run format",
"format": "prettier --write \"src/**/*.{js,jsx,json,md,ts,tsx}\"",
"lint": "eslint src test --fix --ext .js,.ts,.tsx && npm run format",

src/devtools/ReactotronConfig.ts

import { clear } from "app/utils/storage";
import { goBack, resetRoot, navigate } from "app/navigators/navigationUtilities";
import { clear } from "src/utils/storage";
import { goBack, resetRoot, navigate } from "src/navigators/navigationUtilities";

src/components/ListView.ts

import { isRTL } from "app/i18n";
import { isRTL } from "src/i18n";
(optional) Additional files to update

test/i18n.test.ts

import en from "../app/i18n/en";
import en from "../src/i18n/en";
import { exec } from "child_process";

ignite/templates/component/NAME.tsx.ejs

---
patch:
path: "app/components/index.ts"
path: "src/components/index.ts"
append: "export * from \"./<%= props.subdirectory %><%= props.pascalCaseName %>\"\n"
skip: <%= props.skipIndexFile %>
---
import * as React from "react"
import { StyleProp, TextStyle, View, ViewStyle } from "react-native"
import { observer } from "mobx-react-lite"
import { colors, typography } from "app/theme"
import { Text } from "app/components/Text"
import { colors, typography } from "src/theme"
import { Text } from "src/components/Text"

ignite/templates/model/NAME.tsx.ejs

---
patches:
- path: "app/models/RootStore.ts"
- path: "src/models/RootStore.ts"
after: "from \"mobx-state-tree\"\n"
insert: "import { <%= props.pascalCaseName %>Model } from \"./<%= props.pascalCaseName %>\"\n"
skip: <%= !props.pascalCaseName.endsWith('Store') %>
- path: "app/models/RootStore.ts"
- path: "src/models/RootStore.ts"
after: "types.model(\"RootStore\").props({\n"
insert: " <%= props.camelCaseName %>: types.optional(<%= props.pascalCaseName %>Model, {} as any),\n"
skip: <%= !props.pascalCaseName.endsWith('Store') %>
- path: "app/models/index.ts"
- path: "src/models/index.ts"

Creating File-based Routes

src/app/_layout.tsx

We're now ready to start setting up navigation for the app! If you're familiar with Ignite, app.tsx is where our root navigator lives, however, with expo-router, we'll use src/app/_layout.tsx for that. We'll add the providers here that any route would need within the app.

// app/_layout.tsx
import React from "react";
import { Slot, SplashScreen } from "expo-router";
import { useInitialRootStore } from "src/models";

SplashScreen.preventAutoHideAsync();

if (__DEV__) {
// Load Reactotron configuration in development. We don't want to
// include this in our production bundle, so we are using `if (__DEV__)`
// to only execute this in development.
require("src/devtools/ReactotronConfig.ts");
}

export { ErrorBoundary } from "src/components/ErrorBoundary/ErrorBoundary";

export default function Root() {
// Wait for stores to load and render our layout inside of it so we have access
// to auth info etc
const { rehydrated } = useInitialRootStore();
if (!rehydrated) {
return null;
}

return <Slot />;
}

Move ErrorBoundary out of screens/ErrorScreen and into src/components/ErrorBoundary:

mkdir src/components/ErrorBoundary
mv src/screens/ErrorScreen/* src/components/ErrorBoundary

For starters, this sets up our error boundary for the app and handles waiting on our stores to rehydrate. <Slot /> comes from expo-router, you can think of it like the children prop in React. This component can be wrapped with others to help create a layout.

Next, we'll convert the conditional part of authentication from react-navigation to expo-router, deciding on whether or not to display the login form or get to the welcome screen experience.

src/app/(app)/_layout.tsx

Create another _layout.tsx but this time inside of a new directory, src/app/(app). This route wrapped in parentheses is called a Group. Groups can be used to add layouts and/or help organize sections of the app without adding additional segments to the URL. Remember, each directory is a route in this new mental model of file-based routing - but sometimes we don't want that, that's when you'll call upon groups.

In this layout is where we'll determine if the user is authenticated by checking our MST store. We'll also wait here while assets are loaded and then hide the splash screen when finished.

import React from "react";
import { Redirect, SplashScreen, Stack } from "expo-router";
import { observer } from "mobx-react-lite";
import { useStores } from "src/models";
import { useFonts } from "expo-font";
import { customFontsToLoad } from "src/theme";

export default observer(function Layout() {
const {
authenticationStore: { isAuthenticated },
} = useStores();

const [fontsLoaded, fontError] = useFonts(customFontsToLoad);

React.useEffect(() => {
if (fontsLoaded || fontError) {
// Hide the splash screen after the fonts have loaded and the UI is ready.
SplashScreen.hideAsync();
}
}, [fontsLoaded, fontError]);

if (!fontsLoaded && !fontError) {
return null;
}

if (!isAuthenticated) {
return <Redirect href="/log-in" />;
}

return <Stack screenOptions={{ headerShown: false }} />;
});

As you can see, if the user is not authenticated we redirect them to the /log-in route, otherwise we'll render a stack navigator. TypeScript is probably telling us that route doesn't exist yet, so let's fix that.

src/app/log-in.tsx

To redirect the user to the login form, create src/app/log-in.tsx. We'll copy over the contents from the original boilerplate src/screens/LoginScreen.tsx to help the UI layout of this page.

src/app/log-in.tsx
import { router } from "expo-router";
import { observer } from "mobx-react-lite";
import React, { ComponentType, useEffect, useMemo, useRef, useState } from "react";
import { TextInput, TextStyle, ViewStyle } from "react-native";
import { Button, Icon, Screen, Text, TextField, TextFieldAccessoryProps } from "src/components";
import { useStores } from "src/models";
import { colors, spacing } from "src/theme";

export default observer(function Login(_props) {
const authPasswordInput = useRef<TextInput>(null);

const [authPassword, setAuthPassword] = useState("");
const [isAuthPasswordHidden, setIsAuthPasswordHidden] = useState(true);
const [isSubmitted, setIsSubmitted] = useState(false);
const [attemptsCount, setAttemptsCount] = useState(0);
const {
authenticationStore: { authEmail, setAuthEmail, setAuthToken, validationError },
} = useStores();

useEffect(() => {
// Here is where you could fetch credentials from keychain or storage
// and pre-fill the form fields.
setAuthEmail("ignite@infinite.red");
setAuthPassword("ign1teIsAwes0m3");

// Return a "cleanup" function that React will run when the component unmounts
return () => {
setAuthPassword("");
setAuthEmail("");
};
}, []);

const error = isSubmitted ? validationError : "";

function login() {
setIsSubmitted(true);
setAttemptsCount(attemptsCount + 1);

if (validationError) return;

// Make a request to your server to get an authentication token.
// If successful, reset the fields and set the token.
setIsSubmitted(false);
setAuthPassword("");
setAuthEmail("");

// We'll mock this with a fake token.
setAuthToken(String(Date.now()));

// navigate to the main screen
router.replace("/");
}

const PasswordRightAccessory: ComponentType<TextFieldAccessoryProps> = useMemo(
() =>
function PasswordRightAccessory(props: TextFieldAccessoryProps) {
return (
<Icon
icon={isAuthPasswordHidden ? "view" : "hidden"}
color={colors.palette.neutral800}
containerStyle={props.style}
size={20}
onPress={() => setIsAuthPasswordHidden(!isAuthPasswordHidden)}
/>
);
},
[isAuthPasswordHidden]
);

return (
<Screen preset="auto" contentContainerStyle={$screenContentContainer} safeAreaEdges={["top", "bottom"]}>
<Text testID="login-heading" tx="loginScreen.signIn" preset="heading" style={$signIn} />
<Text tx="loginScreen.enterDetails" preset="subheading" style={$enterDetails} />
{attemptsCount > 2 && <Text tx="loginScreen.hint" size="sm" weight="light" style={$hint} />}

<TextField
value={authEmail}
onChangeText={setAuthEmail}
containerStyle={$textField}
autoCapitalize="none"
autoComplete="email"
autoCorrect={false}
keyboardType="email-address"
labelTx="loginScreen.emailFieldLabel"
placeholderTx="loginScreen.emailFieldPlaceholder"
helper={error}
status={error ? "error" : undefined}
onSubmitEditing={() => authPasswordInput.current?.focus()}
/>

<TextField
ref={authPasswordInput}
value={authPassword}
onChangeText={setAuthPassword}
containerStyle={$textField}
autoCapitalize="none"
autoComplete="password"
autoCorrect={false}
secureTextEntry={isAuthPasswordHidden}
labelTx="loginScreen.passwordFieldLabel"
placeholderTx="loginScreen.passwordFieldPlaceholder"
onSubmitEditing={login}
RightAccessory={PasswordRightAccessory}
/>

<Button testID="login-button" tx="loginScreen.tapToSignIn" style={$tapButton} preset="reversed" onPress={login} />
</Screen>
);
});

const $screenContentContainer: ViewStyle = {
paddingVertical: spacing.xxl,
paddingHorizontal: spacing.lg,
};

const $signIn: TextStyle = {
marginBottom: spacing.sm,
};

const $enterDetails: TextStyle = {
marginBottom: spacing.lg,
};

const $hint: TextStyle = {
color: colors.tint,
marginBottom: spacing.md,
};

const $textField: ViewStyle = {
marginBottom: spacing.lg,
};

const $tapButton: ViewStyle = {
marginTop: spacing.xs,
};

If you're familiar with the Ignite boilerplate, this is the same authentication screen you are used to - the only difference here is some of the imports now from from src/* rather than the relative paths. So keep that in mind if you're upgrading an existing application.

src/app/(app)/index.tsx

If the user is successfully authenticated, we'll show them the welcome screen. Can you guess what the route will be by looking at the directory structure?

Just the root route! Think about it in terms of web URLs, if arriving at http://localhost:8081/ (in this case of local development), we'd expect to see the welcome screen. However, if we're not authenticated, we'll be redirected to /log-in to ask the user to log in.

This JSX will be the same exact contents from WelcomeScreen.tsx in the original Ignite boilerplate with the exception of some import paths (using the TS aliases) and a simple update to goNext.

Since we'll no longer use the navigation prop, we utilize expo-router's Imperative navigation to navigate to the component demo Showroom next. We're using .replace since we don't need to get back to this route. You can read more about Navigating between pages at Expo's documentation.

src/app/(app)/index.tsx
import { router } from "expo-router";
import { observer } from "mobx-react-lite";
import React from "react";
import { Image, ImageStyle, TextStyle, View, ViewStyle } from "react-native";
import { Button, Text } from "src/components";
import { isRTL } from "src/i18n";
import { useStores } from "src/models";
import { colors, spacing } from "src/theme";
import { useHeader } from "src/utils/useHeader";
import { useSafeAreaInsetsStyle } from "src/utils/useSafeAreaInsetsStyle";

const welcomeLogo = require("assets/images/logo.png");
const welcomeFace = require("assets/images/welcome-face.png");

export default observer(function WelcomeScreen() {
const {
authenticationStore: { logout },
} = useStores();

function goNext() {
router.replace("/showroom");
}

useHeader(
{
rightTx: "common.logOut",
onRightPress: logout,
},
[logout]
);

const $bottomContainerInsets = useSafeAreaInsetsStyle(["bottom"]);

return (
<View style={$container}>
<View style={$topContainer}>
<Image style={$welcomeLogo} source={welcomeLogo} resizeMode="contain" />
<Text testID="welcome-heading" style={$welcomeHeading} tx="welcomeScreen.readyForLaunch" preset="heading" />
<Text tx="welcomeScreen.exciting" preset="subheading" />
<Image style={$welcomeFace} source={welcomeFace} resizeMode="contain" />
</View>

<View style={[$bottomContainer, $bottomContainerInsets]}>
<Text tx="welcomeScreen.postscript" size="md" />
<Button testID="next-screen-button" preset="reversed" tx="welcomeScreen.letsGo" onPress={goNext} />
</View>
</View>
);
});

const $container: ViewStyle = {
flex: 1,
backgroundColor: colors.background,
};

const $topContainer: ViewStyle = {
flexShrink: 1,
flexGrow: 1,
flexBasis: "57%",
justifyContent: "center",
paddingHorizontal: spacing.lg,
};

const $bottomContainer: ViewStyle = {
flexShrink: 1,
flexGrow: 0,
flexBasis: "43%",
backgroundColor: colors.palette.neutral100,
borderTopLeftRadius: 16,
borderTopRightRadius: 16,
paddingHorizontal: spacing.lg,
justifyContent: "space-around",
};
const $welcomeLogo: ImageStyle = {
height: 88,
width: "100%",
marginBottom: spacing.xxl,
};

const $welcomeFace: ImageStyle = {
height: 169,
width: 269,
position: "absolute",
bottom: -47,
right: -80,
transform: [{ scaleX: isRTL ? -1 : 1 }],
};

const $welcomeHeading: TextStyle = {
marginBottom: spacing.md,
};

Checkpoint

Build and run your app using yarn run ios. You should see the log-in route, be able to authenticate, and navigate to the main "welcome" screen. But we aren't done yet - we still need to add the remaining screens in a Tab Navigator.

Adding Tab Navigation

First, we'll create another route group to help contain where these routes live and set the layout for the tabs.

Create src/app/(app)/(tabs)/_layout.tsx and we'll convert Ignite's previous app/navigators/DemoNavigator.tsx to live here.

src/app/(app)/(tabs)/_layout.tsx
import React from "react";
import { Tabs } from "expo-router/tabs";
import { observer } from "mobx-react-lite";
import { Icon } from "src/components";
import { translate } from "src/i18n";
import { colors, spacing, typography } from "src/theme";
import { TextStyle, ViewStyle } from "react-native";
import { useSafeAreaInsets } from "react-native-safe-area-context";

export default observer(function Layout() {
const { bottom } = useSafeAreaInsets();

return (
<Tabs
screenOptions={{
headerShown: false,
tabBarHideOnKeyboard: true,
tabBarStyle: [$tabBar, { height: bottom + 70 }],
tabBarActiveTintColor: colors.text,
tabBarInactiveTintColor: colors.text,
tabBarLabelStyle: $tabBarLabel,
tabBarItemStyle: $tabBarItem,
}}
>
<Tabs.Screen
name="showroom"
options={{
href: "/showroom",
headerShown: false,
tabBarLabel: translate("demoNavigator.componentsTab"),
tabBarIcon: ({ focused }) => <Icon icon="components" color={focused ? colors.tint : undefined} size={30} />,
}}
/>
<Tabs.Screen
name="community"
options={{
href: "/community",
headerShown: false,
tabBarLabel: translate("demoNavigator.communityTab"),
tabBarIcon: ({ focused }) => <Icon icon="community" color={focused ? colors.tint : undefined} size={30} />,
}}
/>
<Tabs.Screen
name="podcasts"
options={{
href: "/podcasts",
headerShown: false,
tabBarAccessibilityLabel: translate("demoNavigator.podcastListTab"),
tabBarLabel: translate("demoNavigator.podcastListTab"),
tabBarIcon: ({ focused }) => <Icon icon="podcast" color={focused ? colors.tint : undefined} size={30} />,
}}
/>
<Tabs.Screen
name="debug"
options={{
href: "/debug",
headerShown: false,
tabBarLabel: translate("demoNavigator.debugTab"),
tabBarIcon: ({ focused }) => <Icon icon="debug" color={focused ? colors.tint : undefined} size={30} />,
}}
/>
</Tabs>
);
});

const $tabBar: ViewStyle = {
backgroundColor: colors.background,
borderTopColor: colors.transparent,
};

const $tabBarItem: ViewStyle = {
paddingTop: spacing.md,
};

const $tabBarLabel: TextStyle = {
fontSize: 12,
fontFamily: typography.primary.medium,
lineHeight: 16,
flex: 1,
};

Creating Tab Screens

Now to create screens for each tabs, you simply just add [screen].tsx under the (tabs) group. Let's bring over the 3 simpler screens first - Community, Podcasts and Debug. Those will mostly be copy 🍝 aside from changing the exports to default and import from our TS paths.

src/app/(app)/(tabs)/community.tsx
import React from "react";
import { Image, ImageStyle, TextStyle, View, ViewStyle } from "react-native";
import { ListItem, Screen, Text } from "src/components";
import { spacing } from "src/theme";
import { openLinkInBrowser } from "src/utils/openLinkInBrowser";
import { isRTL } from "src/i18n";

const chainReactLogo = require("assets/images/demo/cr-logo.png");
const reactNativeLiveLogo = require("assets/images/demo/rnl-logo.png");
const reactNativeRadioLogo = require("assets/images/demo/rnr-logo.png");
const reactNativeNewsletterLogo = require("assets/images/demo/rnn-logo.png");

export default function DemoCommunityScreen() {
return (
<Screen preset="scroll" contentContainerStyle={$container} safeAreaEdges={["top"]}>
<Text preset="heading" tx="demoCommunityScreen.title" style={$title} />
<Text tx="demoCommunityScreen.tagLine" style={$tagline} />

<Text preset="subheading" tx="demoCommunityScreen.joinUsOnSlackTitle" />
<Text tx="demoCommunityScreen.joinUsOnSlack" style={$description} />
<ListItem
tx="demoCommunityScreen.joinSlackLink"
leftIcon="slack"
rightIcon={isRTL ? "caretLeft" : "caretRight"}
onPress={() => openLinkInBrowser("https://community.infinite.red/")}
/>
<Text preset="subheading" tx="demoCommunityScreen.makeIgniteEvenBetterTitle" style={$sectionTitle} />
<Text tx="demoCommunityScreen.makeIgniteEvenBetter" style={$description} />
<ListItem
tx="demoCommunityScreen.contributeToIgniteLink"
leftIcon="github"
rightIcon={isRTL ? "caretLeft" : "caretRight"}
onPress={() => openLinkInBrowser("https://github.com/infinitered/ignite")}
/>

<Text preset="subheading" tx="demoCommunityScreen.theLatestInReactNativeTitle" style={$sectionTitle} />
<Text tx="demoCommunityScreen.theLatestInReactNative" style={$description} />
<ListItem
tx="demoCommunityScreen.reactNativeRadioLink"
bottomSeparator
rightIcon={isRTL ? "caretLeft" : "caretRight"}
LeftComponent={
<View style={$logoContainer}>
<Image source={reactNativeRadioLogo} style={$logo} />
</View>
}
onPress={() => openLinkInBrowser("https://reactnativeradio.com/")}
/>
<ListItem
tx="demoCommunityScreen.reactNativeNewsletterLink"
bottomSeparator
rightIcon={isRTL ? "caretLeft" : "caretRight"}
LeftComponent={
<View style={$logoContainer}>
<Image source={reactNativeNewsletterLogo} style={$logo} />
</View>
}
onPress={() => openLinkInBrowser("https://reactnativenewsletter.com/")}
/>
<ListItem
tx="demoCommunityScreen.reactNativeLiveLink"
bottomSeparator
rightIcon={isRTL ? "caretLeft" : "caretRight"}
LeftComponent={
<View style={$logoContainer}>
<Image source={reactNativeLiveLogo} style={$logo} />
</View>
}
onPress={() => openLinkInBrowser("https://rn.live/")}
/>
<ListItem
tx="demoCommunityScreen.chainReactConferenceLink"
rightIcon={isRTL ? "caretLeft" : "caretRight"}
LeftComponent={
<View style={$logoContainer}>
<Image source={chainReactLogo} style={$logo} />
</View>
}
onPress={() => openLinkInBrowser("https://cr.infinite.red/")}
/>
<Text preset="subheading" tx="demoCommunityScreen.hireUsTitle" style={$sectionTitle} />
<Text tx="demoCommunityScreen.hireUs" style={$description} />
<ListItem
tx="demoCommunityScreen.hireUsLink"
leftIcon="clap"
rightIcon={isRTL ? "caretLeft" : "caretRight"}
onPress={() => openLinkInBrowser("https://infinite.red/contact")}
/>
</Screen>
);
}

const $container: ViewStyle = {
paddingTop: spacing.lg + spacing.xl,
paddingHorizontal: spacing.lg,
};

const $title: TextStyle = {
marginBottom: spacing.sm,
};

const $tagline: TextStyle = {
marginBottom: spacing.xxl,
};

const $description: TextStyle = {
marginBottom: spacing.lg,
};

const $sectionTitle: TextStyle = {
marginTop: spacing.xxl,
};

const $logoContainer: ViewStyle = {
marginEnd: spacing.md,
flexDirection: "row",
flexWrap: "wrap",
alignContent: "center",
};

const $logo: ImageStyle = {
height: 38,
width: 38,
};
src/app/(app)/(tabs)/podcasts.tsx
import { observer } from "mobx-react-lite";
import React, { ComponentType, useEffect, useMemo } from "react";
import {
AccessibilityProps,
ActivityIndicator,
Image,
ImageSourcePropType,
ImageStyle,
Platform,
StyleSheet,
TextStyle,
View,
ViewStyle,
} from "react-native";
import { type ContentStyle } from "@shopify/flash-list";
import Animated, {
Extrapolate,
interpolate,
useAnimatedStyle,
useSharedValue,
withSpring,
} from "react-native-reanimated";
import { Button, ButtonAccessoryProps, Card, EmptyState, Icon, ListView, Screen, Text, Toggle } from "src/components";
import { isRTL, translate } from "src/i18n";
import { useStores } from "src/models";
import { Episode } from "src/models/Episode";
import { colors, spacing } from "src/theme";
import { delay } from "src/utils/delay";
import { openLinkInBrowser } from "src/utils/openLinkInBrowser";

const ICON_SIZE = 14;

const rnrImage1 = require("assets/images/demo/rnr-image-1.png");
const rnrImage2 = require("assets/images/demo/rnr-image-2.png");
const rnrImage3 = require("assets/images/demo/rnr-image-3.png");
const rnrImages = [rnrImage1, rnrImage2, rnrImage3];

export default observer(function DemoPodcastListScreen(_props) {
const { episodeStore } = useStores();

const [refreshing, setRefreshing] = React.useState(false);
const [isLoading, setIsLoading] = React.useState(false);

// initially, kick off a background refresh without the refreshing UI
useEffect(() => {
(async function load() {
setIsLoading(true);
await episodeStore.fetchEpisodes();
setIsLoading(false);
})();
}, [episodeStore]);

// simulate a longer refresh, if the refresh is too fast for UX
async function manualRefresh() {
setRefreshing(true);
await Promise.all([episodeStore.fetchEpisodes(), delay(750)]);
setRefreshing(false);
}

return (
<Screen preset="fixed" safeAreaEdges={["top"]} contentContainerStyle={$screenContentContainer}>
<ListView<Episode>
contentContainerStyle={$listContentContainer}
data={episodeStore.episodesForList.slice()}
extraData={episodeStore.favorites.length + episodeStore.episodes.length}
refreshing={refreshing}
estimatedItemSize={177}
onRefresh={manualRefresh}
ListEmptyComponent={
isLoading ? (
<ActivityIndicator />
) : (
<EmptyState
preset="generic"
style={$emptyState}
headingTx={episodeStore.favoritesOnly ? "demoPodcastListScreen.noFavoritesEmptyState.heading" : undefined}
contentTx={episodeStore.favoritesOnly ? "demoPodcastListScreen.noFavoritesEmptyState.content" : undefined}
button={episodeStore.favoritesOnly ? "" : undefined}
buttonOnPress={manualRefresh}
imageStyle={$emptyStateImage}
ImageProps={{ resizeMode: "contain" }}
/>
)
}
ListHeaderComponent={
<View style={$heading}>
<Text preset="heading" tx="demoPodcastListScreen.title" />
{(episodeStore.favoritesOnly || episodeStore.episodesForList.length > 0) && (
<View style={$toggle}>
<Toggle
value={episodeStore.favoritesOnly}
onValueChange={() => episodeStore.setProp("favoritesOnly", !episodeStore.favoritesOnly)}
variant="switch"
labelTx="demoPodcastListScreen.onlyFavorites"
labelPosition="left"
labelStyle={$labelStyle}
accessibilityLabel={translate("demoPodcastListScreen.accessibility.switch")}
/>
</View>
)}
</View>
}
renderItem={({ item }) => (
<EpisodeCard
episode={item}
isFavorite={episodeStore.hasFavorite(item)}
onPressFavorite={() => episodeStore.toggleFavorite(item)}
/>
)}
/>
</Screen>
);
});

const EpisodeCard = observer(function EpisodeCard({
episode,
isFavorite,
onPressFavorite,
}: {
episode: Episode;
onPressFavorite: () => void;
isFavorite: boolean;
}) {
const liked = useSharedValue(isFavorite ? 1 : 0);

const imageUri = useMemo<ImageSourcePropType>(() => {
return rnrImages[Math.floor(Math.random() * rnrImages.length)];
}, []);

// Grey heart
const animatedLikeButtonStyles = useAnimatedStyle(() => {
return {
transform: [
{
scale: interpolate(liked.value, [0, 1], [1, 0], Extrapolate.EXTEND),
},
],
opacity: interpolate(liked.value, [0, 1], [1, 0], Extrapolate.CLAMP),
};
});

// Pink heart
const animatedUnlikeButtonStyles = useAnimatedStyle(() => {
return {
transform: [
{
scale: liked.value,
},
],
opacity: liked.value,
};
});

/**
* Android has a "longpress" accessibility action. iOS does not, so we just have to use a hint.
* @see https://reactnative.dev/docs/accessibility#accessibilityactions
*/
const accessibilityHintProps = useMemo(
() =>
Platform.select<AccessibilityProps>({
ios: {
accessibilityLabel: episode.title,
accessibilityHint: translate("demoPodcastListScreen.accessibility.cardHint", {
action: isFavorite ? "unfavorite" : "favorite",
}),
},
android: {
accessibilityLabel: episode.title,
accessibilityActions: [
{
name: "longpress",
label: translate("demoPodcastListScreen.accessibility.favoriteAction"),
},
],
onAccessibilityAction: ({ nativeEvent }) => {
if (nativeEvent.actionName === "longpress") {
handlePressFavorite();
}
},
},
}),
[episode, isFavorite]
);

const handlePressFavorite = () => {
onPressFavorite();
liked.value = withSpring(liked.value ? 0 : 1);
};

const handlePressCard = () => {
openLinkInBrowser(episode.enclosure.link);
};

const ButtonLeftAccessory: ComponentType<ButtonAccessoryProps> = useMemo(
() =>
function ButtonLeftAccessory() {
return (
<View>
<Animated.View style={[$iconContainer, StyleSheet.absoluteFill, animatedLikeButtonStyles]}>
<Icon
icon="heart"
size={ICON_SIZE}
color={colors.palette.neutral800} // dark grey
/>
</Animated.View>
<Animated.View style={[$iconContainer, animatedUnlikeButtonStyles]}>
<Icon
icon="heart"
size={ICON_SIZE}
color={colors.palette.primary400} // pink
/>
</Animated.View>
</View>
);
},
[]
);

return (
<Card
style={$item}
verticalAlignment="force-footer-bottom"
onPress={handlePressCard}
onLongPress={handlePressFavorite}
HeadingComponent={
<View style={$metadata}>
<Text style={$metadataText} size="xxs" accessibilityLabel={episode.datePublished.accessibilityLabel}>
{episode.datePublished.textLabel}
</Text>
<Text style={$metadataText} size="xxs" accessibilityLabel={episode.duration.accessibilityLabel}>
{episode.duration.textLabel}
</Text>
</View>
}
content={`${episode.parsedTitleAndSubtitle.title} - ${episode.parsedTitleAndSubtitle.subtitle}`}
{...accessibilityHintProps}
RightComponent={<Image source={imageUri} style={$itemThumbnail} />}
FooterComponent={
<Button
onPress={handlePressFavorite}
onLongPress={handlePressFavorite}
style={[$favoriteButton, isFavorite && $unFavoriteButton]}
accessibilityLabel={
isFavorite
? translate("demoPodcastListScreen.accessibility.unfavoriteIcon")
: translate("demoPodcastListScreen.accessibility.favoriteIcon")
}
LeftAccessory={ButtonLeftAccessory}
>
<Text
size="xxs"
accessibilityLabel={episode.duration.accessibilityLabel}
weight="medium"
text={
isFavorite
? translate("demoPodcastListScreen.unfavoriteButton")
: translate("demoPodcastListScreen.favoriteButton")
}
/>
</Button>
}
/>
);
});

const $screenContentContainer: ViewStyle = {
flex: 1,
};

const $listContentContainer: ContentStyle = {
paddingHorizontal: spacing.lg,
paddingTop: spacing.lg + spacing.xl,
paddingBottom: spacing.lg,
};

const $heading: ViewStyle = {
marginBottom: spacing.md,
};

const $item: ViewStyle = {
padding: spacing.md,
marginTop: spacing.md,
minHeight: 120,
};

const $itemThumbnail: ImageStyle = {
marginTop: spacing.sm,
borderRadius: 50,
alignSelf: "flex-start",
};

const $toggle: ViewStyle = {
marginTop: spacing.md,
};

const $labelStyle: TextStyle = {
textAlign: "left",
};

const $iconContainer: ViewStyle = {
height: ICON_SIZE,
width: ICON_SIZE,
flexDirection: "row",
marginEnd: spacing.sm,
};

const $metadata: TextStyle = {
color: colors.textDim,
marginTop: spacing.xs,
flexDirection: "row",
};

const $metadataText: TextStyle = {
color: colors.textDim,
marginEnd: spacing.md,
marginBottom: spacing.xs,
};

const $favoriteButton: ViewStyle = {
borderRadius: 17,
marginTop: spacing.md,
justifyContent: "flex-start",
backgroundColor: colors.palette.neutral300,
borderColor: colors.palette.neutral300,
paddingHorizontal: spacing.md,
paddingTop: spacing.xxxs,
paddingBottom: 0,
minHeight: 32,
alignSelf: "flex-start",
};

const $unFavoriteButton: ViewStyle = {
borderColor: colors.palette.primary100,
backgroundColor: colors.palette.primary100,
};

const $emptyState: ViewStyle = {
marginTop: spacing.xxl,
};

const $emptyStateImage: ImageStyle = {
transform: [{ scaleX: isRTL ? -1 : 1 }],
};
src/app/(app)/(tabs)/debug.tsx
import React from "react";
import * as Application from "expo-application";
import { Linking, Platform, TextStyle, View, ViewStyle } from "react-native";
import { Button, ListItem, Screen, Text } from "src/components";
import { colors, spacing } from "src/theme";
import { isRTL } from "src/i18n";
import { useStores } from "src/models";

function openLinkInBrowser(url: string) {
Linking.canOpenURL(url).then((canOpen) => canOpen && Linking.openURL(url));
}

export default function DemoDebugScreen() {
const {
authenticationStore: { logout },
} = useStores();

const usingHermes = typeof HermesInternal === "object" && HermesInternal !== null;
// @ts-expect-error
const usingFabric = global.nativeFabricUIManager != null;

const demoReactotron = React.useMemo(
() => async () => {
if (__DEV__) {
console.tron.display({
name: "DISPLAY",
value: {
appId: Application.applicationId,
appName: Application.applicationName,
appVersion: Application.nativeApplicationVersion,
appBuildVersion: Application.nativeBuildVersion,
hermesEnabled: usingHermes,
},
important: true,
});
}
},
[]
);

return (
<Screen preset="scroll" safeAreaEdges={["top"]} contentContainerStyle={$container}>
<Text
style={$reportBugsLink}
tx="demoDebugScreen.reportBugs"
onPress={() => openLinkInBrowser("https://github.com/infinitered/ignite/issues")}
/>
<Text style={$title} preset="heading" tx="demoDebugScreen.title" />
<View style={$itemsContainer}>
<ListItem
LeftComponent={
<View style={$item}>
<Text preset="bold">App Id</Text>
<Text>{Application.applicationId}</Text>
</View>
}
/>
<ListItem
LeftComponent={
<View style={$item}>
<Text preset="bold">App Name</Text>
<Text>{Application.applicationName}</Text>
</View>
}
/>
<ListItem
LeftComponent={
<View style={$item}>
<Text preset="bold">App Version</Text>
<Text>{Application.nativeApplicationVersion}</Text>
</View>
}
/>
<ListItem
LeftComponent={
<View style={$item}>
<Text preset="bold">App Build Version</Text>
<Text>{Application.nativeBuildVersion}</Text>
</View>
}
/>
<ListItem
LeftComponent={
<View style={$item}>
<Text preset="bold">Hermes Enabled</Text>
<Text>{String(usingHermes)}</Text>
</View>
}
/>
<ListItem
LeftComponent={
<View style={$item}>
<Text preset="bold">Fabric Enabled</Text>
<Text>{String(usingFabric)}</Text>
</View>
}
/>
</View>
<View style={$buttonContainer}>
<Button style={$button} tx="demoDebugScreen.reactotron" onPress={demoReactotron} />
<Text style={$hint} tx={`demoDebugScreen.${Platform.OS}ReactotronHint` as const} />
</View>
<View style={$buttonContainer}>
<Button style={$button} tx="common.logOut" onPress={logout} />
</View>
</Screen>
);
}

const $container: ViewStyle = {
paddingTop: spacing.lg + spacing.xl,
paddingBottom: spacing.xxl,
paddingHorizontal: spacing.lg,
};

const $title: TextStyle = {
marginBottom: spacing.xxl,
};

const $reportBugsLink: TextStyle = {
color: colors.tint,
marginBottom: spacing.lg,
alignSelf: isRTL ? "flex-start" : "flex-end",
};

const $item: ViewStyle = {
marginBottom: spacing.md,
};

const $itemsContainer: ViewStyle = {
marginBottom: spacing.xl,
};

const $button: ViewStyle = {
marginBottom: spacing.xs,
};

const $buttonContainer: ViewStyle = {
marginBottom: spacing.md,
};

const $hint: TextStyle = {
color: colors.palette.neutral600,
fontSize: 12,
lineHeight: 15,
paddingBottom: spacing.lg,
};

These will all be navigable by routing to /community, /podcasts or /debug. Next we'll cover the Showroom which is a bit more involved, since we have to add some supporting components that only apply to that route.

Showroom Screen

The Showroom screen has some supporting components it needs that only applies to that route. Ignite used to colocate these next to the screen file itself, in the src/app/screens/DemoShowroomScreen directory. However, expo-router wants to keep the app directory strictly for app routes.

To adhere to this, we'll move the supporting components to src/components/Showroom and import them from their in our src/app/(app)/(tabs)/showroom.tsx.

mv src/screens/DemoShowroomScreen src/components/Showroom
rm src/components/Showroom/DemoShowroomScreen.tsx

Note: There is a type that gets removed by the above command. Add the following to the top of src/components/Showroom/demos/index.ts

import { ReactElement } from "react";

export interface Demo {
name: string;
description: string;
data: ReactElement[];
}

You'll need to update the imports in the src/components/Showroom/demos/Demo*.ts files. +A project-wide search and replace should do the trick:

  • Project-wide search for from "../DemoShowroomScreen"
  • Replace with from "."

We've deleted the screen file because we'll make a few expo-router specific changes to it over in the app directory. One improvement we can make to the Showroom screen is that we can reduce the platform specific code with regards to the renderItem of SectionList.

Before, we had an implementation for both web and mobile to help with some specific web routing for deep links:

const WebListItem: FC<DemoListItem> = ({ item, sectionIndex }) => {
const sectionSlug = item.name.toLowerCase();

return (
<View>
<Link to={`/showroom/${sectionSlug}`} style={$menuContainer}>
<Text preset="bold">{item.name}</Text>
</Link>
{item.useCases.map((u) => {
const itemSlug = slugify(u);

return (
<Link key={`section${sectionIndex}-${u}`} to={`/showroom/${sectionSlug}/${itemSlug}`}>
<Text>{u}</Text>
</Link>
);
})}
</View>
);
};

const NativeListItem: FC<DemoListItem> = ({ item, sectionIndex, handleScroll }) => (
<View>
<Text onPress={() => handleScroll?.(sectionIndex)} preset="bold" style={$menuContainer}>
{item.name}
</Text>
{item.useCases.map((u, index) => (
<ListItem
key={`section${sectionIndex}-${u}`}
onPress={() => handleScroll?.(sectionIndex, index + 1)}
text={u}
rightIcon={isRTL ? "caretLeft" : "caretRight"}
/>
))}
</View>
);

const ShowroomListItem = Platform.select({
web: WebListItem,
default: NativeListItem,
});

However, we don't have to worry about this anymore. We can implement this as follows:

const ShowroomListItem: FC<DemoListItem> = ({ item, sectionIndex }) => {
const sectionSlug = item.name.toLowerCase();

return (
<View>
<Link href={{ pathname: "/showroom", params: { sectionSlug } }}>
<Text preset="bold">{item.name}</Text>
</Link>
{item.useCases.map((u) => {
const itemSlug = slugify(u);
return (
<Link
key={`section${sectionIndex}-${u}`}
href={{ pathname: "/showroom", params: { sectionSlug, itemSlug } }}
asChild
>
<ListItem text={u} rightIcon={isRTL ? "caretLeft" : "caretRight"} />
</Link>
);
})}
</View>
);
};

Note the Link wrapper provided by expo-router. We link to the /showroom route and provide the extra search params for a section or specific component we want to navigate to. We can then extract (and type) these params using useLocalSearchParams

The snippet below contains the entire file for reference:

src/app/(app)/(tabs)/showroom.tsx
import React, { FC, useEffect, useRef, useState } from "react";
import { Image, ImageStyle, SectionList, TextStyle, View, ViewStyle } from "react-native";
import { Drawer } from "react-native-drawer-layout";
import { type ContentStyle } from "@shopify/flash-list";
import { ListItem, ListView, ListViewRef, Screen, Text } from "src/components";
import { isRTL } from "src/i18n";
import { colors, spacing } from "src/theme";
import { useSafeAreaInsetsStyle } from "src/utils/useSafeAreaInsetsStyle";
import * as Demos from "src/components/Showroom/demos";
import { DrawerIconButton } from "src/components/Showroom/DrawerIconButton";
import { Link, useLocalSearchParams } from "expo-router";

const logo = require("assets/images/logo.png");

interface DemoListItem {
item: { name: string; useCases: string[] };
sectionIndex: number;
handleScroll?: (sectionIndex: number, itemIndex?: number) => void;
}

const slugify = (str: string) =>
str
.toLowerCase()
.trim()
.replace(/[^\w\s-]/g, "")
.replace(/[\s_-]+/g, "-")
.replace(/^-+|-+$/g, "");

const ShowroomListItem: FC<DemoListItem> = ({ item, sectionIndex }) => {
const sectionSlug = item.name.toLowerCase();

return (
<View>
<Link href={{ pathname: "/showroom", params: { sectionSlug } }}>
<Text preset="bold">{item.name}</Text>
</Link>
{item.useCases.map((u) => {
const itemSlug = slugify(u);
return (
<Link
key={`section${sectionIndex}-${u}`}
href={{ pathname: "/showroom", params: { sectionSlug, itemSlug } }}
asChild
>
<ListItem text={u} rightIcon={isRTL ? "caretLeft" : "caretRight"} />
</Link>
);
})}
</View>
);
};

export default function DemoShowroomScreen() {
const [open, setOpen] = useState(false);
const timeout = useRef<ReturnType<typeof setTimeout>>();
const listRef = useRef<SectionList>(null);
const menuRef = useRef<ListViewRef<DemoListItem["item"]>>(null);

const params = useLocalSearchParams<{
sectionSlug?: string;
itemSlug?: string;
}>();

// handle scroll when section/item params change
React.useEffect(() => {
if (Object.keys(params).length > 0) {
const demoValues = Object.values(Demos);
const findSectionIndex = demoValues.findIndex((x) => x.name.toLowerCase() === params.sectionSlug);
let findItemIndex = 0;
if (params.itemSlug) {
try {
findItemIndex =
demoValues[findSectionIndex].data.findIndex((u) => slugify(u.props.name) === params.itemSlug) + 1;
} catch (err) {
console.error(err);
}
}
handleScroll(findSectionIndex, findItemIndex);
}
}, [params]);

const toggleDrawer = () => {
if (!open) {
setOpen(true);
} else {
setOpen(false);
}
};

const handleScroll = (sectionIndex: number, itemIndex = 0) => {
listRef.current?.scrollToLocation({
animated: true,
itemIndex,
sectionIndex,
});
toggleDrawer();
};

const scrollToIndexFailed = (info: {
index: number;
highestMeasuredFrameIndex: number;
averageItemLength: number;
}) => {
listRef.current?.getScrollResponder()?.scrollToEnd();
timeout.current = setTimeout(
() =>
listRef.current?.scrollToLocation({
animated: true,
itemIndex: info.index,
sectionIndex: 0,
}),
50
);
};

useEffect(() => {
return () => timeout.current && clearTimeout(timeout.current);
}, []);

const $drawerInsets = useSafeAreaInsetsStyle(["top"]);

return (
<Drawer
open={open}
onOpen={() => setOpen(true)}
onClose={() => setOpen(false)}
drawerType={"slide"}
drawerPosition={isRTL ? "right" : "left"}
renderDrawerContent={() => (
<View style={[$drawer, $drawerInsets]}>
<View style={$logoContainer}>
<Image source={logo} style={$logoImage} />
</View>

<ListView<DemoListItem["item"]>
ref={menuRef}
contentContainerStyle={$listContentContainer}
estimatedItemSize={250}
data={Object.values(Demos).map((d) => ({
name: d.name,
useCases: d.data.map((u) => u.props.name as string),
}))}
keyExtractor={(item) => item.name}
renderItem={({ item, index: sectionIndex }) => (
<ShowroomListItem {...{ item, sectionIndex, handleScroll }} />
)}
/>
</View>
)}
>
<Screen preset="fixed" safeAreaEdges={["top"]} contentContainerStyle={$screenContainer}>
<DrawerIconButton onPress={toggleDrawer} {...{ open }} />

<SectionList
ref={listRef}
contentContainerStyle={$sectionListContentContainer}
stickySectionHeadersEnabled={false}
sections={Object.values(Demos)}
renderItem={({ item }) => item}
renderSectionFooter={() => <View style={$demoUseCasesSpacer} />}
ListHeaderComponent={
<View style={$heading}>
<Text preset="heading" tx="demoShowroomScreen.jumpStart" />
</View>
}
onScrollToIndexFailed={scrollToIndexFailed}
renderSectionHeader={({ section }) => {
return (
<View>
<Text preset="heading" style={$demoItemName}>
{section.name}
</Text>
<Text style={$demoItemDescription}>{section.description}</Text>
</View>
);
}}
/>
</Screen>
</Drawer>
);
}

const $screenContainer: ViewStyle = {
flex: 1,
};

const $drawer: ViewStyle = {
backgroundColor: colors.background,
flex: 1,
};

const $listContentContainer: ContentStyle = {
paddingHorizontal: spacing.lg,
};

const $sectionListContentContainer: ViewStyle = {
paddingHorizontal: spacing.lg,
};

const $heading: ViewStyle = {
marginBottom: spacing.xxxl,
};

const $logoImage: ImageStyle = {
height: 42,
width: 77,
};

const $logoContainer: ViewStyle = {
alignSelf: "flex-start",
justifyContent: "center",
height: 56,
paddingHorizontal: spacing.lg,
};

const $demoItemName: TextStyle = {
fontSize: 24,
marginBottom: spacing.md,
};

const $demoItemDescription: TextStyle = {
marginBottom: spacing.xxl,
};

const $demoUseCasesSpacer: ViewStyle = {
paddingBottom: spacing.xxl,
};

If you head on over to the web app at http://localhost:8081/showroom?itemSlug=variants&sectionSlug=toggle, you'll see the Showroom screen will open and scroll down to the appropriate section.

We can emulate deep links in Expo Go with the command:

npx uri-scheme open exp://localhost:8081/--/showroom --ios

Observe the simulator opens the mobile app and navigates to the Showroom screen.

We get that universal linking for free with expo-router!

Code Cleanup

Now that we have the boilerplate up and running again, let's clean some of the screen and navigation files that are no longer needed.

rm src/app.tsx
rm -rf src/screens
rm -rf src/navigators

In doing so, we'll need to fix some Reacetotron code for custom commands. We'll drop the resetNavigation one (logging out is really the same thing) and update the navigateTo and goBack. Open up src/devtools/ReactotronConfig.ts to edit these.

import { goBack, resetRoot, navigate } from "src/navigators/navigationUtilities";
import { router } from "expo-router";
// ...
reactotron.onCustomCommand({
title: "Reset Navigation State",
description: "Resets the navigation state",
command: "resetNavigation",
handler: () => {
Reactotron.log("resetting navigation state");
resetRoot({ index: 0, routes: [] });
},
});

reactotron.onCustomCommand<[{ name: "route"; type: ArgType.String }]>({
command: "navigateTo",
handler: (args) => {
const { route } = args ?? {};
if (route) {
Reactotron.log(`Navigating to: ${route}`);
navigate(route as any); // this should be tied to the navigator, but since this is for debugging, we can navigate to illegal routes
// @ts-ignore - bypass Expo Router Typed Routes
router.push(route);
} else {
Reactotron.log("Could not navigate. No route provided.");
}
},
title: "Navigate To Screen",
description: "Navigates to a screen by name.",
args: [{ name: "route", type: ArgType.String }],
});

reactotron.onCustomCommand({
title: "Go Back",
description: "Goes back",
command: "goBack",
handler: () => {
Reactotron.log("Going back");
goBack();
router.back();
},
});

Summary

There you have it, a culinary masterpiece of Ignite and Expo Router, shipped in one pizza box. What we achieved here:

  • Simplified navigation code
  • Typed routing
  • Examples of many aspects of expo-router, such as authentication, tab navigation, search params
  • Deep linking that Just WorksTM on both web and mobile
  • Reduced Platform specific code

Full Example Repo

Additional Resources

To go more in-depth on expo-router, check out the official documentation at Expo.dev.

You can also follow Evan Bacon, the author of Expo Router, on GitHub and check out his applications or demos using the navigation library.

Additionally, here is an Ignite repo with expo-router added in for reference on my GitHub.

Is this page still up to date? Did it work for you?

+ + + + \ No newline at end of file diff --git a/docs/recipes/GeneratorComponentTests/index.html b/docs/recipes/GeneratorComponentTests/index.html index c05e37ee..388418db 100644 --- a/docs/recipes/GeneratorComponentTests/index.html +++ b/docs/recipes/GeneratorComponentTests/index.html @@ -8,8 +8,8 @@ Generator for Component Tests | Ignite Cookbook for React Native - - + +
@@ -35,8 +35,8 @@

Have an recipe idea for the cookbook? Contribute your ideas on GitHub!

-

Add component tests to npx ignite-cli generate component

Did you know that Ignite automatically generates files for you? And that you can customize those generators?

Here is how to automatically generate components and tests for them using @testing-library/react-native

Setup @testing-library/react-native

First, we will want to add @testing-library/react-native to our Ignite project. Josh Justice has an excellent setup guide to follow along at reactnativetesting.io

Component Generators

There are a variety of generators, but today we are going to focus on npx ignite-cli generate component

Ignite will look in the ignite/templates/* directory for what templates to run on each command.

By default, Ignite provides a ignite/templates/component/NAME.tsx.ejs template for creating a component file.

  • We use ejs and frontmatter to write our templates, you can read more about syntax in the Ignite docs.
  • NAME in ignite/templates/component/NAME.tsx.ejs is replaced with the first argument passed to our generator. So npx ignite-cli generate component Profile would create app/components/Profile.tsx

Customizing Component Generators

Add the following file to ignite/templates/component/NAME.spec.tsx.ejs

---
destinationDir: app/components/specs
---
// https://reactnativetesting.io/component/testing/

import React from "react"
import { fireEvent, render, screen } from "@testing-library/react-native"
import { <%= props.pascalCaseName %> } from "../<%= props.pascalCaseName %>"

describe("<%= props.pascalCaseName %>", () => {
it("renders", () => {
render(<<%= props.pascalCaseName %> />)
expect(screen.getByText("Hello")).toBeTruthy()
})
})

Now, when we run npx ignite-cli generate component Profile, it will create both app/components/Profile.tsx and app/components/specs/Profile.spec.tsx

  • ignite/templates/component/NAME.spec.tsx.ejs
  • ignite/templates/component/NAME.tsx.ejs

Testing

Now, all we need to do is run yarn test! If everything was set up properly, you should have a new suite of passing tests!

Is this page still up to date? Did it work for you?

- - +

Add component tests to npx ignite-cli generate component

Did you know that Ignite automatically generates files for you? And that you can customize those generators?

Here is how to automatically generate components and tests for them using @testing-library/react-native

Setup @testing-library/react-native

First, we will want to add @testing-library/react-native to our Ignite project. Josh Justice has an excellent setup guide to follow along at reactnativetesting.io

Component Generators

There are a variety of generators, but today we are going to focus on npx ignite-cli generate component

Ignite will look in the ignite/templates/* directory for what templates to run on each command.

By default, Ignite provides a ignite/templates/component/NAME.tsx.ejs template for creating a component file.

  • We use ejs and frontmatter to write our templates, you can read more about syntax in the Ignite docs.
  • NAME in ignite/templates/component/NAME.tsx.ejs is replaced with the first argument passed to our generator. So npx ignite-cli generate component Profile would create app/components/Profile.tsx

Customizing Component Generators

Add the following file to ignite/templates/component/NAME.spec.tsx.ejs

---
destinationDir: app/components/specs
---
// https://reactnativetesting.io/component/testing/

import React from "react"
import { fireEvent, render, screen } from "@testing-library/react-native"
import { <%= props.pascalCaseName %> } from "../<%= props.pascalCaseName %>"

describe("<%= props.pascalCaseName %>", () => {
it("renders", () => {
render(<<%= props.pascalCaseName %> />)
expect(screen.getByText("Hello")).toBeTruthy()
})
})

Now, when we run npx ignite-cli generate component Profile, it will create both app/components/Profile.tsx and app/components/specs/Profile.spec.tsx

  • ignite/templates/component/NAME.spec.tsx.ejs
  • ignite/templates/component/NAME.tsx.ejs

Testing

Now, all we need to do is run yarn test! If everything was set up properly, you should have a new suite of passing tests!

Is this page still up to date? Did it work for you?

+ + \ No newline at end of file diff --git a/docs/recipes/MaestroSetup/index.html b/docs/recipes/MaestroSetup/index.html index 466abda3..1b14aeeb 100644 --- a/docs/recipes/MaestroSetup/index.html +++ b/docs/recipes/MaestroSetup/index.html @@ -8,8 +8,8 @@ Maestro Setup | Ignite Cookbook for React Native - - + +
@@ -35,11 +35,11 @@

Have an recipe idea for the cookbook? Contribute your ideas on GitHub!

-

Setting Up Maestro in Ignite

Overview

End-to-end (e2e) testing is a critical part of any application but it can be difficult to set up and maintain. Maestro is a tool that promises to be easy to set up and maintain e2e tests. This recipe will walk you through setting up Maestro in your Ignite project.

Maestro Installation

We're going to start by installing Maestro via the terminal. To do this, we'll need to run the following command:

curl -Ls "https://get.maestro.mobile.dev" | bash

If you haven't already, you'll also need to install Facebook's IDB Companion tool:

brew tap facebook/fb
brew install idb-companion

If you run into any issues, check out the Maestro cli installation guide for more information.

Once the installation is complete, you'll be ready to create your first Maestro flow!

Creating our first Maestro Flow

To start out, we're going to create a folder to hold our Maestro flows. Let's do this by adding a folder in the root of our Ignite project called .maestro. Once that's done we can create our first flow in a file called Login.yaml

With this flow we want to open up our app and then login with the default credentials. We can do this by adding the following to our Login.yaml file:

#flow: Login
#intent:
# Open up our app and use the default credentials to login
# and navigate to the demo screen

appId: com.maestroapp # the app id of the app we want to test
# You can find the appId of an Ignite app in the `app.json` file
# as the "package" under the "android" section and "bundleIdentifier" under the "ios" section
---
- clearState # clears the state of our app (navigation and authentication)
- launchApp # launches the app
- assertVisible: "Sign In"
- tapOn:
text: "Tap to sign in!"
- assertVisible: "Your app, almost ready for launch!"
- tapOn:
text: "Let's go!"
- assertVisible: "Components to jump start your project!"

We're using a few different actions and assertions in this flow. Let's take a look at what they do:

clearState - This action clears the state of our app. This is useful if we want to start from a clean slate. +

Setting Up Maestro in Ignite

Overview

End-to-end (e2e) testing is a critical part of any application but it can be difficult to set up and maintain. Maestro is a tool that promises to be easy to set up and maintain e2e tests. This recipe will walk you through setting up Maestro in your Ignite project.

Maestro Installation

We're going to start by installing Maestro via the terminal. To do this, we'll need to run the following command:

curl -Ls "https://get.maestro.mobile.dev" | bash

If you haven't already, you'll also need to install Facebook's IDB Companion tool:

brew tap facebook/fb
brew install idb-companion

If you run into any issues, check out the Maestro cli installation guide for more information.

Once the installation is complete, you'll be ready to create your first Maestro flow!

Creating our first Maestro Flow

To start out, we're going to create a folder to hold our Maestro flows. Let's do this by adding a folder in the root of our Ignite project called .maestro. Once that's done we can create our first flow in a file called Login.yaml

With this flow we want to open up our app and then login with the default credentials. We can do this by adding the following to our Login.yaml file:

#flow: Login
#intent:
# Open up our app and use the default credentials to login
# and navigate to the demo screen

appId: com.maestroapp # the app id of the app we want to test
# You can find the appId of an Ignite app in the `app.json` file
# as the "package" under the "android" section and "bundleIdentifier" under the "ios" section
---
- clearState # clears the state of our app (navigation and authentication)
- launchApp # launches the app
- assertVisible: "Sign In"
- tapOn:
text: "Tap to sign in!"
- assertVisible: "Your app, almost ready for launch!"
- tapOn:
text: "Let's go!"
- assertVisible: "Components to jump start your project!"

We're using a few different actions and assertions in this flow. Let's take a look at what they do:

clearState - This action clears the state of our app. This is useful if we want to start from a clean slate. launchApp - This action launches our app specified with the appId in our flow. assertVisible - This assertion checks to see if the text we pass in is visible on the screen. tapOn - This action taps on the specified element. In our case, we're tapping on the text we pass in.

To run our flow, first make sure the app is loaded on the simulator or running via metro through yarn ios. If you're using Expo Go, you'll need to do a development build in Expo CNG first. Then execute maestro from its test directory with the following command:

cd .maestro
maestro test Login.yaml

And that's it! We've successfully created our first Maestro flow and ran it. You should see something like this in your terminal after running the test:

> Flow
Running on iPhone 11 - iOS 16.2 - 5A269AA1-2704-429B-BF30-D6965060E03E
║ ✅ Clear state of com.maestroapp
║ ✅ Launch app "com.maestroapp"
║ ✅ Assert that "Sign In" is visible
║ ✅ Tap on "Tap to sign in!"
║ ✅ Assert that "Your app, almost ready for launch!" is visible
║ ✅ Tap on "Let's go!"
║ ✅ Assert that "Components to jump start your project!" is visible

Let's add another flow to see what else we can do with Maestro!

Let's see what else Maestro can do

Let's create a more advanded flow that spans across multiple screens, we'll want to accomplish the following:

  1. Use environment variables
  2. Run the login flow
  3. Navigate to the demo podcast list screen
  4. Favorite a podcast
  5. Switch the list to only be favorites
  6. Use accessibility labels to find elements

Go ahead and create a flow called FavoritePodcast.yaml and add the following to it:

# flow: run the login flow and then navigate to the demo podcast list screen, favorite a podcast, and then switch the list to only be favorites.

appId: com.maestroapp
env:
TITLE: "RNR 257 - META RESPONDS! How can we improve React Native, part 2"
FAVORITES_TEXT: "Switch on to only show favorites"

---
- runFlow: Login.yaml
- tapOn: "Podcast, tab, 3 of 4"
- assertVisible: "React Native Radio episodes"
- tapOn:
text: ${FAVORITES_TEXT}
- assertVisible: "This looks a bit empty"
- tapOn:
text: ${FAVORITES_TEXT}
- scrollUntilVisible:
element:
text: ${TITLE}
direction: DOWN
timeout: 50000
speed: 40
visibilityPercentage: 100
- longPressOn: ${TITLE}
- scrollUntilVisible:
element:
text: ${FAVORITES_TEXT}
direction: UP
timeout: 50000
speed: 40
visibilityPercentage: 100
- tapOn:
text: ${FAVORITES_TEXT}
- assertVisible: ${TITLE}

We did a few things new here. Let's take a look at what they are:

  1. We added an env section to our flow. This allows us to set environment variables that we can use in our flow. In this case, we're setting the title of the podcast we want to favorite and the favorites toggle label text.
  2. We added a runFlow action. This action allows us to run another flow from within our flow. In this case, we're running the Login.yaml flow before we run the rest of our flow.
  3. We added a scrollUntilVisible action. This will help us find the episode we are looking for because it won't always be available in the first visible content as new episodes are released. This action is also used to scroll back up to toggle the Only Show Favorites switch.
  4. We added a longPressOn action. This action allows us to long press on an element. In this case, we're long pressing on the podcast we want to favorite, we're able to do this because of the accessability action that's associated with the Podcast Card.
  5. The text "Switch on to only show favorites" (or env var ${FAVOREITES_TEXT}) is the accessibility label passed to the Toggle component. Maestro identifies accessibility labels as text as long as that element does not have any text children.

If you're running these tests on an iOS simulator, you may need to add accessibilityLabel: episode.title, to line 180 of DemoPodcastListScreen.tsx in your Ignite project.

Conclusion

Maestro is a great tool for e2e testing. It's easy to set up and maintain. It's also easy to add to your Ignite project. If you want to check out how to use their other features, like Maestro cloud & Maestro Studio, check out their documentation.

Notes

Detox is the default e2e testing tool in Ignite. Should you choose to use Maestro, remove Detox from your project.

Is this page still up to date? Did it work for you?

- - + + \ No newline at end of file diff --git a/docs/recipes/MigratingToMMKV/index.html b/docs/recipes/MigratingToMMKV/index.html index f26fe9b2..80a34f0d 100644 --- a/docs/recipes/MigratingToMMKV/index.html +++ b/docs/recipes/MigratingToMMKV/index.html @@ -8,8 +8,8 @@ Migrating to MMKV | Ignite Cookbook for React Native - - + +
@@ -35,8 +35,8 @@

Have an recipe idea for the cookbook? Contribute your ideas on GitHub!

-

Migrating to MMKV

Overview

MMKV is said to be the fastest key/value storage for React Native. It has encryption support for secure local storage and also uses synchronous storage to simplify your application code.

In this recipe, we'll convert our the Ignite demo project from using AsyncStorage to MMKV:

npx ignite-cli new PizzaApp --yes
cd PizzaApp

Project Dependencies

Install the react-native-mmkv dependency into the project

yarn add react-native-mmkv

Note: No pod install was run here because the scripts set up in an Ignite project take care of that for you!

Code Changes

Open app/utils/storage.tsx and modify the imports:

import AsyncStorage from "@react-native-async-storage/async-storage";
import { MMKV } from "react-native-mmkv";
const storage = new MMKV();

Now we'll remove any reference to AsyncStorage and replace it with the proper API from MMKV

/**
* Loads a string from storage.
*
* @param key The key to fetch.
*/
export async function loadString(key: string): Promise<string | null> {
export function loadString(key: string): string | null {
try {
return await AsyncStorage.getItem(key)
return storage.getString(key);
} catch {
// not sure why this would fail... even reading the RN docs I'm unclear
return null;
}
}

/**
* Saves a string to storage.
*
* @param key The key to fetch.
* @param value The value to store.
*/
export async function saveString(key: string, value: string): Promise<boolean> {
export function saveString(key: string, value: string): boolean {
try {
await AsyncStorage.setItem(key, value)
storage.set(key, value);
return true;
} catch {
return false;
}
}

/**
* Loads something from storage and runs it thru JSON.parse.
*
* @param key The key to fetch.
*/
export async function load(key: string): Promise<any | null> {
export function load(key: string): any | null {
try {
const almostThere = await AsyncStorage.getItem(key)
const almostThere = storage.getString(key);
return JSON.parse(almostThere);
} catch {
return null;
}
}

/**
* Saves an object to storage.
*
* @param key The key to fetch.
* @param value The value to store.
*/
export async function save(key: string, value: any): Promise<boolean> {
export function save(key: string, value: any): boolean {
try {
await AsyncStorage.setItem(key, JSON.stringify(value))
saveString(key, JSON.stringify(value));
return true;
} catch {
return false;
}
}

/**
* Removes something from storage.
*
* @param key The key to kill.
*/
export async function remove(key: string): Promise<void> {
export function remove(key: string): void {
try {
await AsyncStorage.removeItem(key)
storage.delete(key);
} catch {}
}

/**
* Burn it all to the ground.
*/
export async function clear(): Promise<void> {
export function clear(): void {
try {
await AsyncStorage.clear()
storage.clearAll();
} catch {}
}

Run the app in the iOS simulator to test the changes with yarn ios. Navigate to the Podcast List screen:

  1. Press "Tap to sign in!"
  2. Press "Let's go!"
  3. Tap on the "Podcast"

Now let's swipe the app away to close it. Re-open the app to see if the navigation picks up where we left off (which shows our storage is working to remember the navigation key we were last on).

And that's it! Ignite is now configured with react-native-mmkv over AsyncStorage.

Is this page still up to date? Did it work for you?

- - +

Migrating to MMKV

Overview

MMKV is said to be the fastest key/value storage for React Native. It has encryption support for secure local storage and also uses synchronous storage to simplify your application code.

In this recipe, we'll convert our the Ignite demo project from using AsyncStorage to MMKV:

npx ignite-cli new PizzaApp --yes
cd PizzaApp

Project Dependencies

Install the react-native-mmkv dependency into the project

yarn add react-native-mmkv

Note: No pod install was run here because the scripts set up in an Ignite project take care of that for you!

Code Changes

Open app/utils/storage.tsx and modify the imports:

import AsyncStorage from "@react-native-async-storage/async-storage";
import { MMKV } from "react-native-mmkv";
const storage = new MMKV();

Now we'll remove any reference to AsyncStorage and replace it with the proper API from MMKV

/**
* Loads a string from storage.
*
* @param key The key to fetch.
*/
export async function loadString(key: string): Promise<string | null> {
export function loadString(key: string): string | null {
try {
return await AsyncStorage.getItem(key)
return storage.getString(key);
} catch {
// not sure why this would fail... even reading the RN docs I'm unclear
return null;
}
}

/**
* Saves a string to storage.
*
* @param key The key to fetch.
* @param value The value to store.
*/
export async function saveString(key: string, value: string): Promise<boolean> {
export function saveString(key: string, value: string): boolean {
try {
await AsyncStorage.setItem(key, value)
storage.set(key, value);
return true;
} catch {
return false;
}
}

/**
* Loads something from storage and runs it thru JSON.parse.
*
* @param key The key to fetch.
*/
export async function load(key: string): Promise<any | null> {
export function load(key: string): any | null {
try {
const almostThere = await AsyncStorage.getItem(key)
const almostThere = storage.getString(key);
return JSON.parse(almostThere);
} catch {
return null;
}
}

/**
* Saves an object to storage.
*
* @param key The key to fetch.
* @param value The value to store.
*/
export async function save(key: string, value: any): Promise<boolean> {
export function save(key: string, value: any): boolean {
try {
await AsyncStorage.setItem(key, JSON.stringify(value))
saveString(key, JSON.stringify(value));
return true;
} catch {
return false;
}
}

/**
* Removes something from storage.
*
* @param key The key to kill.
*/
export async function remove(key: string): Promise<void> {
export function remove(key: string): void {
try {
await AsyncStorage.removeItem(key)
storage.delete(key);
} catch {}
}

/**
* Burn it all to the ground.
*/
export async function clear(): Promise<void> {
export function clear(): void {
try {
await AsyncStorage.clear()
storage.clearAll();
} catch {}
}

Run the app in the iOS simulator to test the changes with yarn ios. Navigate to the Podcast List screen:

  1. Press "Tap to sign in!"
  2. Press "Let's go!"
  3. Tap on the "Podcast"

Now let's swipe the app away to close it. Re-open the app to see if the navigation picks up where we left off (which shows our storage is working to remember the navigation key we were last on).

And that's it! Ignite is now configured with react-native-mmkv over AsyncStorage.

Is this page still up to date? Did it work for you?

+ + \ No newline at end of file diff --git a/docs/recipes/PatchingBuildingAndroid/index.html b/docs/recipes/PatchingBuildingAndroid/index.html index b8437b50..effdf776 100644 --- a/docs/recipes/PatchingBuildingAndroid/index.html +++ b/docs/recipes/PatchingBuildingAndroid/index.html @@ -8,8 +8,8 @@ Patching/Building Android .aar From Source | Ignite Cookbook for React Native - - + +
@@ -35,12 +35,12 @@

Have an recipe idea for the cookbook? Contribute your ideas on GitHub!

-

Patching/Building Android .aar From Source

Why?

Sometimes, a situation arises when you might want to update the react-native Android source code without upgrading react-native itself. For example, there's a new bug on Android 12 where the application crashes due to some bug with the animation queue. The potential fix is available on the main (unreleased) branch, but your app version is a few patches behind. Another situation is when you simply can't upgrade your react-native version yet, but need a fix from future version. In these cases, you can use this approach to "patch" your Android source files and build new .aar binary and use that for your app.

Official Guides

The official steps to build from source are provided by react-native and you can find them here.

The guid is fairly generic and redundant in some cases if you already have a sufficient react-native development environment setup. The steps below describe what has "worked for me" and they may or may not apply to everyone.

Steps

1 - Fork React-Native And Clone

Go to Github and fork react-native. Pull the forked code down to your system.

Note: The official instructions tell you to clone react-native into your project's node_modules. Don't do this. Just pull it down into your favorite development directory.

2 - Checkout the Correct Commit

If you are following this guide, you are most likely trying to patch react-native Android source files at a specific older version. The easiest way to do this is to checkout the commit specified in the respective version's git tag. +

Patching/Building Android .aar From Source

Why?

Sometimes, a situation arises when you might want to update the react-native Android source code without upgrading react-native itself. For example, there's a new bug on Android 12 where the application crashes due to some bug with the animation queue. The potential fix is available on the main (unreleased) branch, but your app version is a few patches behind. Another situation is when you simply can't upgrade your react-native version yet, but need a fix from future version. In these cases, you can use this approach to "patch" your Android source files and build new .aar binary and use that for your app.

Official Guides

The official steps to build from source are provided by react-native and you can find them here.

The guid is fairly generic and redundant in some cases if you already have a sufficient react-native development environment setup. The steps below describe what has "worked for me" and they may or may not apply to everyone.

Steps

1 - Fork React-Native And Clone

Go to Github and fork react-native. Pull the forked code down to your system.

Note: The official instructions tell you to clone react-native into your project's node_modules. Don't do this. Just pull it down into your favorite development directory.

2 - Checkout the Correct Commit

If you are following this guide, you are most likely trying to patch react-native Android source files at a specific older version. The easiest way to do this is to checkout the commit specified in the respective version's git tag. Branch and Commit History

3 - Install Dependencies

Just type yarn.

4 - Configure the SDK

You will need the version of the SDk specifice in the ./ReactAndroid/build.gradle for compileSdkVersion. You can install it via Android Studio. Android SDK Configuration

5 - Configure the NDK

Check the ./gradle.properties file, ANDROID_NDK_VERSION key, for the version needed. This can be installed from Android Studio as well. Android NDK Configuration

Note: The official docs provide links to NDK archives. Installing through Android Studio is probably easer. One caveat is that I didn't find arm architecture NDKs in Android Studio. It's not a big deal though to use those since you won't do this often.

6 - Configure Paths

Create a local.properties file in the root. This file is gitignored and should be kept as so.

sdk.dir=/Users/path/to/sdk
ndk.dir=/Users/path/to/ndk

Your SDK path is in your Library files (if installed through Android Studio).Your NDK path is inside the SDK path. This is what mine looks like:

sdk.dir=/Users/~Usernamehere~/Library/Android/sdk
ndk.dir=/Users/~Usernamehere~/Library/Android/sdk/ndk/21.4.7075529

Note: The official guides also have you setup shell paths with the same values. Not sure if this is needed. It wasn't for me.

7 - Make the Necessary Changes

Now, you can make any changes in the ./ReactAndroid folder.

8 - Build

Run the following command in the root:

arch -x86_64 ./gradlew :ReactAndroid:installArchives --no-daemon

The first time you run this, it'll take some time. It will also report any syntax/type errors. It will also report any configuration errors.

Note: If you installed an arm compatible NDK, omit the arch -x86_64 from the command

9 - Commit and Push

In your .gitignore, remove the line which ignores the /android/ directory. We'll want to commit this build output from step 7. Commit and push your fork.

10 - Update Project's React-Native

Now that you have build and pushed your changes, you can reference that in your application's package.json. ![package json](<../../static//img/PatchingBuildingAndroid

Note: You'll most likely need to delete/re-install your node_modules as well as run ./android/gradlew clean.

Is this page still up to date? Did it work for you?

- - + + \ No newline at end of file diff --git a/docs/recipes/PristineExpoProject/index.html b/docs/recipes/PristineExpoProject/index.html index 1e5ac586..f2c5c34c 100644 --- a/docs/recipes/PristineExpoProject/index.html +++ b/docs/recipes/PristineExpoProject/index.html @@ -8,8 +8,8 @@ Pristine Expo Project | Ignite Cookbook for React Native - - + +
@@ -35,8 +35,8 @@

Have an recipe idea for the cookbook? Contribute your ideas on GitHub!

-

Pristine Expo Project

Ignite sets your project up ready to run both a bare React Native project or with Expo.

However, if you don't want to manage any of the native files going forward, you can follow these steps to get to an Expo only project structure.

Notes

Keep in mind you may have to adopt the following steps for a different package manager or OS. The following are compatible for the yarn package manager while running on MacOS.

Steps

Project Initialization

npx ignite-cli new PizzaApp --yes
cd PizzaApp

Filesystem Changes

rm -rf android
rm -rf ios
rm index.js # Expo's entry point is App.js
rm metro.config.js # Expo will use the default

Package Changes

yarn remove react-native-bootsplash

Removes a native library pertaining to the splash screen (this will be handled via expo-splash-screen)

yarn remove expo-modules-core

package.json Script Updates

These changes are optional as you can continue to use the prefixed expo: commands, however you might just want a cleaned up scripts section of your package.json.

{
"name": "ignite-eas",
"version": "0.0.1",
"private": true,
"main": "node_modules/expo/AppEntry.js",
"scripts": {
"compile": "tsc --noEmit -p . --pretty",
"format": "prettier --write \"app/**/*.{js,jsx,json,md,ts,tsx}\"",
"lint": "eslint App.js app test --fix --ext .js,.ts,.tsx && npm run format",
"patch": "patch-package",
"test": "jest",
"test:watch": "jest --watch",
"adb": "adb reverse tcp:9090 tcp:9090 && adb reverse tcp:3000 tcp:3000 && adb reverse tcp:9001 tcp:9001 && adb reverse tcp:8081 tcp:8081",
"postinstall": "node ./bin/postInstall",
"clean": "npx react-native-clean-project",
"clean-all": "npx react-native clean-project-auto",
"start": "expo start",
"android": "expo start --android",
"ios": "expo start --ios",
"web": "expo start --web",
"build:detox": "detox build -c ios.sim.expo",
"test:detox": "./bin/downloadExpoApp.sh && detox test --configuration ios.sim.expo"
},
// ... more config ...
"detox": {
"test-runner": "jest",
"runnerConfig": "./detox/config.json",
"specs": "detox",
"configurations": {
"ios.sim.expo": {
"binaryPath": "bin/Exponent.app",
"type": "ios.simulator",
"name": "iPhone 14"
}
}
}
// ... more config ...
}

Is this page still up to date? Did it work for you?

- - +

Pristine Expo Project

Ignite sets your project up ready to run both a bare React Native project or with Expo.

However, if you don't want to manage any of the native files going forward, you can follow these steps to get to an Expo only project structure.

Notes

Keep in mind you may have to adopt the following steps for a different package manager or OS. The following are compatible for the yarn package manager while running on MacOS.

Steps

Project Initialization

npx ignite-cli new PizzaApp --yes
cd PizzaApp

Filesystem Changes

rm -rf android
rm -rf ios
rm index.js # Expo's entry point is App.js
rm metro.config.js # Expo will use the default

Package Changes

yarn remove react-native-bootsplash

Removes a native library pertaining to the splash screen (this will be handled via expo-splash-screen)

yarn remove expo-modules-core

package.json Script Updates

These changes are optional as you can continue to use the prefixed expo: commands, however you might just want a cleaned up scripts section of your package.json.

{
"name": "ignite-eas",
"version": "0.0.1",
"private": true,
"main": "node_modules/expo/AppEntry.js",
"scripts": {
"compile": "tsc --noEmit -p . --pretty",
"format": "prettier --write \"app/**/*.{js,jsx,json,md,ts,tsx}\"",
"lint": "eslint App.js app test --fix --ext .js,.ts,.tsx && npm run format",
"patch": "patch-package",
"test": "jest",
"test:watch": "jest --watch",
"adb": "adb reverse tcp:9090 tcp:9090 && adb reverse tcp:3000 tcp:3000 && adb reverse tcp:9001 tcp:9001 && adb reverse tcp:8081 tcp:8081",
"postinstall": "node ./bin/postInstall",
"clean": "npx react-native-clean-project",
"clean-all": "npx react-native clean-project-auto",
"start": "expo start",
"android": "expo start --android",
"ios": "expo start --ios",
"web": "expo start --web",
"build:detox": "detox build -c ios.sim.expo",
"test:detox": "./bin/downloadExpoApp.sh && detox test --configuration ios.sim.expo"
},
// ... more config ...
"detox": {
"test-runner": "jest",
"runnerConfig": "./detox/config.json",
"specs": "detox",
"configurations": {
"ios.sim.expo": {
"binaryPath": "bin/Exponent.app",
"type": "ios.simulator",
"name": "iPhone 14"
}
}
}
// ... more config ...
}

Is this page still up to date? Did it work for you?

+ + \ No newline at end of file diff --git a/docs/recipes/ReactNativeVisionCamera/index.html b/docs/recipes/ReactNativeVisionCamera/index.html index 0f4c97de..1a7e93c3 100644 --- a/docs/recipes/ReactNativeVisionCamera/index.html +++ b/docs/recipes/ReactNativeVisionCamera/index.html @@ -8,8 +8,8 @@ React Native Vision Camera | Ignite Cookbook for React Native - - + +
@@ -35,8 +35,8 @@

Have an recipe idea for the cookbook? Contribute your ideas on GitHub!

-

VisionCamera

Overview

VisionCamera is a powerful, high-performance React Native Camera library. It's both feature-rich and flexible! The library provides the necessary hooks and functions to easily integrate camera functionality in your app.

In this example, we'll take a look at wiring up a barcode scanner. This tutorial is written for the Ignite v9 Prebuild workflow, however it generally still applies to DIY or even a bare react-native project.

Installation

If you haven't already, spin up a new Ignite application:

npx ignite-cli@latest new PizzaApp --remove-demo --workflow=prebuild --yes
cd PizzaApp

Next, let's install the necessary dependencies. You can see complete installation instructions for react-native-vision-camera here.

npx expo install react-native-vision-camera

Add the plugin to app.json as per the documentation. It'll look like the following if you have the default Ignite template:

"plugins": [
"expo-localization",
[
"expo-build-properties",
{
"ios": {
"newArchEnabled": false
},
"android": {
"newArchEnabled": false
}
}
],
[
"react-native-vision-camera",
{
"cameraPermissionText": "$(PRODUCT_NAME) needs access to your Camera.",
"enableCodeScanner": true
}
]
],

Note: $(PRODUCT_NAME) comes from the iOS project build configuration, this will be populated with the app name at runtime as long as it's configured properly (in this case, it is in the Ignite boilerplate)

To get this native dependency working in our project, we'll need to run prebuild so Expo can execute the proper native code changes for us. Then we can boot up the app on a device.

npx expo prebuild
yarn android

Since the simulators do not offer a good way of testing the camera for this recipe, we'll be creating an Android build to test on an actual device. This is for convenience, as it's a bit easier to achieve than running on an iOS device, however both would work.

Permissions

Before we can get to using the camera on the device, we must get permission from the user to do so. Let's edit the Welcome screen in Ignite to reflect the current permission status and a way to prompt the user.

import { observer } from "mobx-react-lite";
import React, { FC } from "react";
import { AppStackScreenProps } from "../navigators";
import { Camera, CameraPermissionStatus } from "react-native-vision-camera";
import { Linking, View, ViewStyle } from "react-native";
import { Button, Screen, Text } from "app/components";

interface WelcomeScreenProps extends AppStackScreenProps<"Welcome"> {}

export const WelcomeScreen: FC<WelcomeScreenProps> = observer(
function WelcomeScreen(_props) {
const [cameraPermission, setCameraPermission] =
React.useState<CameraPermissionStatus>();

React.useEffect(() => {
Camera.getCameraPermissionStatus().then(setCameraPermission);
}, []);

const promptForCameraPermissions = React.useCallback(async () => {
const permission = await Camera.requestCameraPermission();
Camera.getCameraPermissionStatus().then(setCameraPermission);

if (permission === "denied") await Linking.openSettings();
}, [cameraPermission]);

if (cameraPermission == null) {
// still loading
return null;
}

return (
<Screen contentContainerStyle={$container}>
<View>
<Text>
Camera Permission:{" "}
{cameraPermission === null ? "Loading..." : cameraPermission}
</Text>
{cameraPermission !== "granted" && (
<Button
onPress={promptForCameraPermissions}
text="Request Camera Permission"
/>
)}
</View>
</Screen>
);
}
);

const $container: ViewStyle = {
flex: 1,
padding: 20,
justifyContent: "space-evenly",
};
Demo Preview

Codes Store & Screen

Before we get to displaying the camera for scanning, let's quickly set up a new store in MST for keeping our list of codes and a screen to view them. Generate the commands using the Ignite CLI:

npx ignite-cli@next g model CodeStore
npx ignite-cli@next g screen Codes

If you're not familiar with generators, head on over to the Ignite Generators documentation to learn more!

Open the generated models/CodeStore.ts. Our Code Store will just have a simple string array and an action to add a new code:

import { Instance, SnapshotIn, SnapshotOut, types } from "mobx-state-tree";
import { withSetPropAction } from "./helpers/withSetPropAction";

/**
* Model description here for TypeScript hints.
*/
export const CodeStoreModel = types
.model("CodeStore")
.props({
codes: types.array(types.string),
})
.actions(withSetPropAction)
.actions((self) => ({
addCode(code: string) {
self.codes.push(code);
},
}));

export interface CodeStore extends Instance<typeof CodeStoreModel> {}
export interface CodeStoreSnapshotOut
extends SnapshotOut<typeof CodeStoreModel> {}
export interface CodeStoreSnapshotIn
extends SnapshotIn<typeof CodeStoreModel> {}
export const createCodeStoreDefaultModel = () =>
types.optional(CodeStoreModel, {});

Next we'll utilize this store on our screens/CodesScreen.tsx. This will just list all of the previously scanned codes and a way to get back to the main screen:

import React, { FC } from "react";
import { observer } from "mobx-react-lite";
import { View, ViewStyle } from "react-native";
import { AppStackScreenProps } from "app/navigators";
import { Button, Screen, Text } from "app/components";
import { useNavigation } from "@react-navigation/native";
import { useStores } from "app/models";
import { spacing } from "app/theme";

interface CodesScreenProps extends AppStackScreenProps<"Codes"> {}

export const CodesScreen: FC<CodesScreenProps> = observer(
function CodesScreen() {
// Pull in one of our MST stores
const { codeStore } = useStores();

// Pull in navigation via hook
const navigation = useNavigation();
return (
<Screen
safeAreaEdges={["top", "bottom"]}
style={$root}
preset="scroll"
contentContainerStyle={$container}
>
<View>
<Text text={`${codeStore.codes.length} codes scanned`} />

{codeStore.codes.map((code, index) => (
<Text key={`code-index-${index}`} text={code} />
))}
</View>

<Button text="Go back" onPress={() => navigation.goBack()} />
</Screen>
);
}
);

const $root: ViewStyle = {
flex: 1,
};

const $container: ViewStyle = {
flex: 1,
justifyContent: "space-between",
paddingHorizontal: spacing.md,
};

Displaying the Camera

We have the dough prepped, we added the sauce - now it's time for the pizza toppings! Back in screens/Welcome.tsx, we'll begin adding more of the camera code by adding the Camera component and wire it up to the useCodeScanner hook, both of which are provided by react-native-vision-camera.

import { observer } from "mobx-react-lite";
import React, { FC } from "react";
import { AppStackScreenProps } from "../navigators";
import {
Camera,
CameraPermissionStatus,
useCameraDevice,
useCodeScanner,
} from "react-native-vision-camera";
import {
Alert,
Linking,
StyleSheet,
TouchableOpacity,
View,
ViewStyle,
} from "react-native";
import { Button, Icon, Screen, Text } from "app/components";
import { useSafeAreaInsets } from "react-native-safe-area-context";
import { useStores } from "app/models";
import { spacing } from "app/theme";

interface WelcomeScreenProps extends AppStackScreenProps<"Welcome"> {}

export const WelcomeScreen: FC<WelcomeScreenProps> = observer(
function WelcomeScreen(_props) {
const [cameraPermission, setCameraPermission] =
React.useState<CameraPermissionStatus>();
const [showScanner, setShowScanner] = React.useState(false);
const [isActive, setIsActive] = React.useState(false);

const { codeStore } = useStores();

React.useEffect(() => {
Camera.getCameraPermissionStatus().then(setCameraPermission);
}, []);

const promptForCameraPermissions = React.useCallback(async () => {
const permission = await Camera.requestCameraPermission();
Camera.getCameraPermissionStatus().then(setCameraPermission);

if (permission === "denied") await Linking.openSettings();
}, [cameraPermission]);

const codeScanner = useCodeScanner({
codeTypes: ["qr", "ean-13"],
onCodeScanned: (codes) => {
setIsActive(false);

codes.every((code) => {
if (code.value) {
codeStore.addCode(code.value);
}
return true;
});

setShowScanner(false);
Alert.alert("Code scanned!");
},
});

const device = useCameraDevice("back");

const { right, top } = useSafeAreaInsets();

if (cameraPermission == null) {
// still loading
return null;
}

if (showScanner && device) {
return (
<View style={$cameraContainer}>
<Camera
isActive={isActive}
device={device}
codeScanner={codeScanner}
style={StyleSheet.absoluteFill}
photo
video
/>
<View
style={[
$cameraButtons,
{ right: right + spacing.md, top: top + spacing.md },
]}
>
<TouchableOpacity
style={$closeCamera}
onPress={() => setShowScanner(false)}
>
<Icon icon="x" size={50} />
</TouchableOpacity>
</View>
</View>
);
}

return (
<Screen contentContainerStyle={$container}>
<View>
<Text>
Camera Permission:{" "}
{cameraPermission === null ? "Loading..." : cameraPermission}
</Text>
{cameraPermission !== "granted" && (
<Button
onPress={promptForCameraPermissions}
text="Request Camera Permission"
/>
)}
</View>
<View>
<Button
onPress={() => {
setIsActive(true);
setShowScanner(true);
}}
text="Scan Barcodes"
/>
</View>
<View>
<Button
onPress={() => _props.navigation.navigate("Codes")}
text={`View Scans (${codeStore.codes.length})`}
/>
</View>
</Screen>
);
}
);

const $container: ViewStyle = {
flex: 1,
padding: 20,
justifyContent: "space-evenly",
};

const $cameraContainer: ViewStyle = {
flex: 1,
};

const $cameraButtons: ViewStyle = {
position: "absolute",
};

const $closeCamera: ViewStyle = {
marginBottom: spacing.md,
width: 100,
height: 100,
borderRadius: 100 / 2,
backgroundColor: "rgba(140, 140, 140, 0.3)",
justifyContent: "center",
alignItems: "center",
};

And that's everything! Check out the Demo Preview to see it in action.

Demo Preview

Is this page still up to date? Did it work for you?

- - +

VisionCamera

Overview

VisionCamera is a powerful, high-performance React Native Camera library. It's both feature-rich and flexible! The library provides the necessary hooks and functions to easily integrate camera functionality in your app.

In this example, we'll take a look at wiring up a barcode scanner. This tutorial is written for the Ignite v9 Prebuild workflow, however it generally still applies to DIY or even a bare react-native project.

Installation

If you haven't already, spin up a new Ignite application:

npx ignite-cli@latest new PizzaApp --remove-demo --workflow=prebuild --yes
cd PizzaApp

Next, let's install the necessary dependencies. You can see complete installation instructions for react-native-vision-camera here.

npx expo install react-native-vision-camera

Add the plugin to app.json as per the documentation. It'll look like the following if you have the default Ignite template:

"plugins": [
"expo-localization",
[
"expo-build-properties",
{
"ios": {
"newArchEnabled": false
},
"android": {
"newArchEnabled": false
}
}
],
[
"react-native-vision-camera",
{
"cameraPermissionText": "$(PRODUCT_NAME) needs access to your Camera.",
"enableCodeScanner": true
}
]
],

Note: $(PRODUCT_NAME) comes from the iOS project build configuration, this will be populated with the app name at runtime as long as it's configured properly (in this case, it is in the Ignite boilerplate)

To get this native dependency working in our project, we'll need to run prebuild so Expo can execute the proper native code changes for us. Then we can boot up the app on a device.

npx expo prebuild
yarn android

Since the simulators do not offer a good way of testing the camera for this recipe, we'll be creating an Android build to test on an actual device. This is for convenience, as it's a bit easier to achieve than running on an iOS device, however both would work.

Permissions

Before we can get to using the camera on the device, we must get permission from the user to do so. Let's edit the Welcome screen in Ignite to reflect the current permission status and a way to prompt the user.

import { observer } from "mobx-react-lite";
import React, { FC } from "react";
import { AppStackScreenProps } from "../navigators";
import { Camera, CameraPermissionStatus } from "react-native-vision-camera";
import { Linking, View, ViewStyle } from "react-native";
import { Button, Screen, Text } from "app/components";

interface WelcomeScreenProps extends AppStackScreenProps<"Welcome"> {}

export const WelcomeScreen: FC<WelcomeScreenProps> = observer(
function WelcomeScreen(_props) {
const [cameraPermission, setCameraPermission] =
React.useState<CameraPermissionStatus>();

React.useEffect(() => {
Camera.getCameraPermissionStatus().then(setCameraPermission);
}, []);

const promptForCameraPermissions = React.useCallback(async () => {
const permission = await Camera.requestCameraPermission();
Camera.getCameraPermissionStatus().then(setCameraPermission);

if (permission === "denied") await Linking.openSettings();
}, [cameraPermission]);

if (cameraPermission == null) {
// still loading
return null;
}

return (
<Screen contentContainerStyle={$container}>
<View>
<Text>
Camera Permission:{" "}
{cameraPermission === null ? "Loading..." : cameraPermission}
</Text>
{cameraPermission !== "granted" && (
<Button
onPress={promptForCameraPermissions}
text="Request Camera Permission"
/>
)}
</View>
</Screen>
);
}
);

const $container: ViewStyle = {
flex: 1,
padding: 20,
justifyContent: "space-evenly",
};
Demo Preview

Codes Store & Screen

Before we get to displaying the camera for scanning, let's quickly set up a new store in MST for keeping our list of codes and a screen to view them. Generate the commands using the Ignite CLI:

npx ignite-cli@next g model CodeStore
npx ignite-cli@next g screen Codes

If you're not familiar with generators, head on over to the Ignite Generators documentation to learn more!

Open the generated models/CodeStore.ts. Our Code Store will just have a simple string array and an action to add a new code:

import { Instance, SnapshotIn, SnapshotOut, types } from "mobx-state-tree";
import { withSetPropAction } from "./helpers/withSetPropAction";

/**
* Model description here for TypeScript hints.
*/
export const CodeStoreModel = types
.model("CodeStore")
.props({
codes: types.array(types.string),
})
.actions(withSetPropAction)
.actions((self) => ({
addCode(code: string) {
self.codes.push(code);
},
}));

export interface CodeStore extends Instance<typeof CodeStoreModel> {}
export interface CodeStoreSnapshotOut
extends SnapshotOut<typeof CodeStoreModel> {}
export interface CodeStoreSnapshotIn
extends SnapshotIn<typeof CodeStoreModel> {}
export const createCodeStoreDefaultModel = () =>
types.optional(CodeStoreModel, {});

Next we'll utilize this store on our screens/CodesScreen.tsx. This will just list all of the previously scanned codes and a way to get back to the main screen:

import React, { FC } from "react";
import { observer } from "mobx-react-lite";
import { View, ViewStyle } from "react-native";
import { AppStackScreenProps } from "app/navigators";
import { Button, Screen, Text } from "app/components";
import { useNavigation } from "@react-navigation/native";
import { useStores } from "app/models";
import { spacing } from "app/theme";

interface CodesScreenProps extends AppStackScreenProps<"Codes"> {}

export const CodesScreen: FC<CodesScreenProps> = observer(
function CodesScreen() {
// Pull in one of our MST stores
const { codeStore } = useStores();

// Pull in navigation via hook
const navigation = useNavigation();
return (
<Screen
safeAreaEdges={["top", "bottom"]}
style={$root}
preset="scroll"
contentContainerStyle={$container}
>
<View>
<Text text={`${codeStore.codes.length} codes scanned`} />

{codeStore.codes.map((code, index) => (
<Text key={`code-index-${index}`} text={code} />
))}
</View>

<Button text="Go back" onPress={() => navigation.goBack()} />
</Screen>
);
}
);

const $root: ViewStyle = {
flex: 1,
};

const $container: ViewStyle = {
flex: 1,
justifyContent: "space-between",
paddingHorizontal: spacing.md,
};

Displaying the Camera

We have the dough prepped, we added the sauce - now it's time for the pizza toppings! Back in screens/Welcome.tsx, we'll begin adding more of the camera code by adding the Camera component and wire it up to the useCodeScanner hook, both of which are provided by react-native-vision-camera.

import { observer } from "mobx-react-lite";
import React, { FC } from "react";
import { AppStackScreenProps } from "../navigators";
import {
Camera,
CameraPermissionStatus,
useCameraDevice,
useCodeScanner,
} from "react-native-vision-camera";
import {
Alert,
Linking,
StyleSheet,
TouchableOpacity,
View,
ViewStyle,
} from "react-native";
import { Button, Icon, Screen, Text } from "app/components";
import { useSafeAreaInsets } from "react-native-safe-area-context";
import { useStores } from "app/models";
import { spacing } from "app/theme";

interface WelcomeScreenProps extends AppStackScreenProps<"Welcome"> {}

export const WelcomeScreen: FC<WelcomeScreenProps> = observer(
function WelcomeScreen(_props) {
const [cameraPermission, setCameraPermission] =
React.useState<CameraPermissionStatus>();
const [showScanner, setShowScanner] = React.useState(false);
const [isActive, setIsActive] = React.useState(false);

const { codeStore } = useStores();

React.useEffect(() => {
Camera.getCameraPermissionStatus().then(setCameraPermission);
}, []);

const promptForCameraPermissions = React.useCallback(async () => {
const permission = await Camera.requestCameraPermission();
Camera.getCameraPermissionStatus().then(setCameraPermission);

if (permission === "denied") await Linking.openSettings();
}, [cameraPermission]);

const codeScanner = useCodeScanner({
codeTypes: ["qr", "ean-13"],
onCodeScanned: (codes) => {
setIsActive(false);

codes.every((code) => {
if (code.value) {
codeStore.addCode(code.value);
}
return true;
});

setShowScanner(false);
Alert.alert("Code scanned!");
},
});

const device = useCameraDevice("back");

const { right, top } = useSafeAreaInsets();

if (cameraPermission == null) {
// still loading
return null;
}

if (showScanner && device) {
return (
<View style={$cameraContainer}>
<Camera
isActive={isActive}
device={device}
codeScanner={codeScanner}
style={StyleSheet.absoluteFill}
photo
video
/>
<View
style={[
$cameraButtons,
{ right: right + spacing.md, top: top + spacing.md },
]}
>
<TouchableOpacity
style={$closeCamera}
onPress={() => setShowScanner(false)}
>
<Icon icon="x" size={50} />
</TouchableOpacity>
</View>
</View>
);
}

return (
<Screen contentContainerStyle={$container}>
<View>
<Text>
Camera Permission:{" "}
{cameraPermission === null ? "Loading..." : cameraPermission}
</Text>
{cameraPermission !== "granted" && (
<Button
onPress={promptForCameraPermissions}
text="Request Camera Permission"
/>
)}
</View>
<View>
<Button
onPress={() => {
setIsActive(true);
setShowScanner(true);
}}
text="Scan Barcodes"
/>
</View>
<View>
<Button
onPress={() => _props.navigation.navigate("Codes")}
text={`View Scans (${codeStore.codes.length})`}
/>
</View>
</Screen>
);
}
);

const $container: ViewStyle = {
flex: 1,
padding: 20,
justifyContent: "space-evenly",
};

const $cameraContainer: ViewStyle = {
flex: 1,
};

const $cameraButtons: ViewStyle = {
position: "absolute",
};

const $closeCamera: ViewStyle = {
marginBottom: spacing.md,
width: 100,
height: 100,
borderRadius: 100 / 2,
backgroundColor: "rgba(140, 140, 140, 0.3)",
justifyContent: "center",
alignItems: "center",
};

And that's everything! Check out the Demo Preview to see it in action.

Demo Preview

Is this page still up to date? Did it work for you?

+ + \ No newline at end of file diff --git a/docs/recipes/Redux/index.html b/docs/recipes/Redux/index.html index 51eac526..1670988f 100644 --- a/docs/recipes/Redux/index.html +++ b/docs/recipes/Redux/index.html @@ -8,8 +8,8 @@ Redux | Ignite Cookbook for React Native - - + +
@@ -35,8 +35,8 @@

Have an recipe idea for the cookbook? Contribute your ideas on GitHub!

-

Redux

This guide will show you how to migrate a Mobx-State-Tree project (Ignite's default) to Redux, using a newly created Ignite project as our example:

npx ignite-cli new ReduxApp --yes --removeDemo

If you are migrating an existing project these steps still apply, but you may need to migrate your existing state tree and other additional functionality.

Remove Mobx-State-Tree

  • Remove all Mobx-related dependencies from package.json, then run yarn or npm i
--"mobx": "6.10.2",
--"mobx-react-lite": "4.0.5",
--"mobx-state-tree": "5.3.0",

--"reactotron-mst": "3.1.5",
  • Ignite created default boilerplate Mobx-State-Tree files in the models/ directory. Remove this entire directory and all files within it, these are not needed for Redux.

  • In devtools/ReactotronConfig.ts remove the reactotron-mst plugin. We can come back to add a Redux plugin later.

--import { mst } from "reactotron-mst"

...

const reactotron = Reactotron.configure({
name: require("../../package.json").name,
onConnect: () => {
/** since this file gets hot reloaded, let's clear the past logs every time we connect */
Reactotron.clear()
},
--}).use(
-- mst({
-- /** ignore some chatty `mobx-state-tree` actions */
-- filter: (event) => /postProcessSnapshot|@APPLY_SNAPSHOT/.test(event.name) === false,
-- }),
--)
++})
  • Remove all observer() components and reformat as normal React components. Do a project-wide search for observer( and replace each component instance with the following pattern:
--import { observer } from "mobx-react-lite"

--export const WelcomeScreen: FC<WelcomeScreenProps> = observer(function WelcomeScreen(props) {
++export const WelcomeScreen: FC<WelcomeScreenProps> = (props) => {
...
--})
++}
  • (optional) Don't forget to update your Ignite Generator Templates!
    • Follow the same pattern to replace observer(). This will allow you to quickly generate screens and components via npx ignite-cli generate screen NewScreen and npx ignite-cli generate component NewComponent and use your updated syntax. (You can customize these however you like!)
    • Update ignite/templates/component/NAME.tsx.ejs and ignite/templates/screen/NAMEScreen.tsx.ejs
--import { observer } from "mobx-react-lite"

--export const <%= props.pascalCaseName %> = observer(function <%= props.pascalCaseName %>(props: <%= props.pascalCaseName %>Props) {
++export const <%= props.pascalCaseName %> = (props: <%= props.pascalCaseName %>Props) => {
...
--})
++}
  • Remove old Mobx-State-Tree store initialization / hydration code in app.tsx.
  • Call hideSplashScreen in a useEffect so the app loads for now. We'll replace this code when we add persistence below.
--import { useInitialRootStore } from "./models"

--const { rehydrated } = useInitialRootStore(() => {
--setTimeout(hideSplashScreen, 500)
--})
++useEffect(() => {
++ setTimeout(hideSplashScreen, 500)
++}, [])

--if (!rehydrated || !isNavigationStateRestored || !areFontsLoaded) return null
++if (!isNavigationStateRestored || !areFontsLoaded) return null

You should be able to build and run your app! It won't have any data...but it's a good idea to check that it successfully runs before we move on.

Add Redux

Install dependencies

redux-tooklit is the current recommended approach, and you'll also need react-redux bindings for your React Native app.

yarn add @reduxjs/toolkit
yarn add react-redux

Create Store

  • In a new file app/store.ts, create your Redux store.
    • Create an initial store. We're using Redux Toolkit's configureStore here for simplicity.
    • Export Typescript helpers for the rest of your app to stay type safe

store.ts

import { configureStore } from "@reduxjs/toolkit";
import { TypedUseSelectorHook, useDispatch, useSelector } from "react-redux";
import counterReducer from "./counterSlice";

export const store = configureStore({
reducer: {
counter: counterReducer,
// add other state here
},
});

// Infer the `RootState` and `AppDispatch` types from the store itself
export type RootState = ReturnType<typeof store.getState>;
export type AppDispatch = typeof store.dispatch;

// Use throughout app instead of plain `useDispatch` and `useSelector` for type safety
type DispatchFunc = () => AppDispatch;
export const useAppDispatch: DispatchFunc = useDispatch;
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector;

Add State

  • Add your state reducers or slices. We'll create a simple counter slice for this example.
  • If you have an existing state tree with Mobx-State-Tree, you'll need to convert your tree into a series of Redux reducers.
    • Note: Redux does not define or validate your models like Mobx-State-Tree does. It is up to you to ensure the correct data is being set in your reducers.

counterSlice.ts

import { createSlice } from "@reduxjs/toolkit";

// Define a type for the slice state
interface CounterState {
value: number;
}

// Define the initial state using that type
const initialState: CounterState = {
value: 0,
};

export const counterSlice = createSlice({
name: "counter",
// `createSlice` will infer the state type from the `initialState` argument
initialState,
reducers: {
increment: (state) => {
state.value += 1;
},
decrement: (state) => {
state.value -= 1;
},
},
});

export const { increment, decrement } = counterSlice.actions;
export default counterSlice.reducer;

Add Redux Provider

In app.tsx, wrap your AppNavigator with the react-redux Provider component

import { Provider } from "react-redux";
import { store } from "./store/store";

...

<Provider store={store}>
<AppNavigator
linking={linking}
initialState={initialNavigationState}
onStateChange={onNavigationStateChange}
/>
</Provider>

Hook up Components

You can now use selectors to grab data and dispatch() to execute actions within your components. Here's an example:

  • Remember to use our exported useAppSelector and useAppDispatch helpers for type safety

WelcomeScreen.tsx

import React, { FC } from "react";
import { View, ViewStyle } from "react-native";
import { Button, Text } from "app/components";
import { AppStackScreenProps } from "../navigators";
import { colors } from "../theme";
import { useSafeAreaInsetsStyle } from "../utils/useSafeAreaInsetsStyle";
import { useAppDispatch, useAppSelector } from "app/store/store";
import { decrement, increment } from "app/store/counterSlice";

interface WelcomeScreenProps extends AppStackScreenProps<"Welcome"> {}

export const WelcomeScreen: FC<WelcomeScreenProps> = () => {
const $containerInsets = useSafeAreaInsetsStyle(["top", "bottom"]);
const count = useAppSelector((state) => state.counter.value);
const dispatch = useAppDispatch();
return (
<View style={[$containerInsets, $container]}>
<Button text="Increment" onPress={() => dispatch(increment())} />
<Button text="Decrement" onPress={() => dispatch(decrement())} />
<Text text={`Count: ${count}`} />
</View>
);
};

const $container: ViewStyle = {
flex: 1,
backgroundColor: colors.background,
};

You're now using Redux!

Persistence

Ignite ships with built-in persistence support for Mobx-State-Tree. We can add similar support for Redux by:

  1. Install redux-persist
yarn add redux-persist
  1. Modify store.ts to include redux-persist

store.ts

import { combineReducers, configureStore } from "@reduxjs/toolkit";
import counterReducer from "./counterSlice";
import { TypedUseSelectorHook, useDispatch, useSelector } from "react-redux";
import {
persistStore,
persistReducer,
FLUSH,
REHYDRATE,
PAUSE,
PERSIST,
PURGE,
REGISTER,
} from "redux-persist";
import AsyncStorage from "@react-native-async-storage/async-storage";

const persistConfig = {
key: "root",
version: 1,
storage: AsyncStorage,
};

const rootReducer = combineReducers({
counter: counterReducer,
});

const persistedReducer = persistReducer(persistConfig, rootReducer);

export const store = configureStore({
reducer: persistedReducer,
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware({
serializableCheck: {
ignoredActions: [FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER],
},
}),
});

export const persistor = persistStore(store);

// Infer the `RootState` and `AppDispatch` types from the store itself
export type RootState = ReturnType<typeof store.getState>;
export type AppDispatch = typeof store.dispatch;

// Use throughout app instead of plain `useDispatch` and `useSelector` for type safety
type DispatchFunc = () => AppDispatch;
export const useAppDispatch: DispatchFunc = useDispatch;
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector;
  1. Add a PersistGate to app.tsx and replace any existing hideSplashScreen calls with the onBeforeLift callback

app.tsx

...

import { persistor, store } from "./store/store"
import { PersistGate } from "redux-persist/integration/react"

...

function App(props: AppProps) {
const { hideSplashScreen } = props
...
const onBeforeLiftPersistGate = () => {
// If your initialization scripts run very fast, it's good to show the splash screen for just a bit longer to prevent flicker.
// Slightly delaying splash screen hiding for better UX; can be customized or removed as needed,
// Note: (vanilla Android) The splash-screen will not appear if you launch your app via the terminal or Android Studio. Kill the app and launch it normally by tapping on the launcher icon. https://stackoverflow.com/a/69831106
// Note: (vanilla iOS) You might notice the splash-screen logo change size. This happens in debug/development mode. Try building the app for release.
setTimeout(hideSplashScreen, 500)
}
...
return (
<SafeAreaProvider initialMetrics={initialWindowMetrics}>
<ErrorBoundary catchErrors={Config.catchErrors}>
<GestureHandlerRootView style={$container}>
<Provider store={store}>
<PersistGate
loading={null}
onBeforeLift={onBeforeLiftPersistGate}
persistor={persistor}
>
<AppNavigator
linking={linking}
initialState={initialNavigationState}
onStateChange={onNavigationStateChange}
/>
</PersistGate>
</Provider>
</GestureHandlerRootView>
</ErrorBoundary>
</SafeAreaProvider>
)
}

export default App

Your Redux state should now be persisted using AsyncStorage!

Reactotron Support

Reactotron has a prebuilt plugin for Redux!

Follow the instructions to install

Is this page still up to date? Did it work for you?

- - +

Redux

This guide will show you how to migrate a Mobx-State-Tree project (Ignite's default) to Redux, using a newly created Ignite project as our example:

npx ignite-cli new ReduxApp --yes --removeDemo

If you are migrating an existing project these steps still apply, but you may need to migrate your existing state tree and other additional functionality.

Remove Mobx-State-Tree

  • Remove all Mobx-related dependencies from package.json, then run yarn or npm i
--"mobx": "6.10.2",
--"mobx-react-lite": "4.0.5",
--"mobx-state-tree": "5.3.0",

--"reactotron-mst": "3.1.5",
  • Ignite created default boilerplate Mobx-State-Tree files in the models/ directory. Remove this entire directory and all files within it, these are not needed for Redux.

  • In devtools/ReactotronConfig.ts remove the reactotron-mst plugin. We can come back to add a Redux plugin later.

--import { mst } from "reactotron-mst"

...

const reactotron = Reactotron.configure({
name: require("../../package.json").name,
onConnect: () => {
/** since this file gets hot reloaded, let's clear the past logs every time we connect */
Reactotron.clear()
},
--}).use(
-- mst({
-- /** ignore some chatty `mobx-state-tree` actions */
-- filter: (event) => /postProcessSnapshot|@APPLY_SNAPSHOT/.test(event.name) === false,
-- }),
--)
++})
  • Remove all observer() components and reformat as normal React components. Do a project-wide search for observer( and replace each component instance with the following pattern:
--import { observer } from "mobx-react-lite"

--export const WelcomeScreen: FC<WelcomeScreenProps> = observer(function WelcomeScreen(props) {
++export const WelcomeScreen: FC<WelcomeScreenProps> = (props) => {
...
--})
++}
  • (optional) Don't forget to update your Ignite Generator Templates!
    • Follow the same pattern to replace observer(). This will allow you to quickly generate screens and components via npx ignite-cli generate screen NewScreen and npx ignite-cli generate component NewComponent and use your updated syntax. (You can customize these however you like!)
    • Update ignite/templates/component/NAME.tsx.ejs and ignite/templates/screen/NAMEScreen.tsx.ejs
--import { observer } from "mobx-react-lite"

--export const <%= props.pascalCaseName %> = observer(function <%= props.pascalCaseName %>(props: <%= props.pascalCaseName %>Props) {
++export const <%= props.pascalCaseName %> = (props: <%= props.pascalCaseName %>Props) => {
...
--})
++}
  • Remove old Mobx-State-Tree store initialization / hydration code in app.tsx.
  • Call hideSplashScreen in a useEffect so the app loads for now. We'll replace this code when we add persistence below.
--import { useInitialRootStore } from "./models"

--const { rehydrated } = useInitialRootStore(() => {
--setTimeout(hideSplashScreen, 500)
--})
++useEffect(() => {
++ setTimeout(hideSplashScreen, 500)
++}, [])

--if (!rehydrated || !isNavigationStateRestored || !areFontsLoaded) return null
++if (!isNavigationStateRestored || !areFontsLoaded) return null

You should be able to build and run your app! It won't have any data...but it's a good idea to check that it successfully runs before we move on.

Add Redux

Install dependencies

redux-tooklit is the current recommended approach, and you'll also need react-redux bindings for your React Native app.

yarn add @reduxjs/toolkit
yarn add react-redux

Create Store

  • In a new file app/store.ts, create your Redux store.
    • Create an initial store. We're using Redux Toolkit's configureStore here for simplicity.
    • Export Typescript helpers for the rest of your app to stay type safe

store.ts

import { configureStore } from "@reduxjs/toolkit";
import { TypedUseSelectorHook, useDispatch, useSelector } from "react-redux";
import counterReducer from "./counterSlice";

export const store = configureStore({
reducer: {
counter: counterReducer,
// add other state here
},
});

// Infer the `RootState` and `AppDispatch` types from the store itself
export type RootState = ReturnType<typeof store.getState>;
export type AppDispatch = typeof store.dispatch;

// Use throughout app instead of plain `useDispatch` and `useSelector` for type safety
type DispatchFunc = () => AppDispatch;
export const useAppDispatch: DispatchFunc = useDispatch;
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector;

Add State

  • Add your state reducers or slices. We'll create a simple counter slice for this example.
  • If you have an existing state tree with Mobx-State-Tree, you'll need to convert your tree into a series of Redux reducers.
    • Note: Redux does not define or validate your models like Mobx-State-Tree does. It is up to you to ensure the correct data is being set in your reducers.

counterSlice.ts

import { createSlice } from "@reduxjs/toolkit";

// Define a type for the slice state
interface CounterState {
value: number;
}

// Define the initial state using that type
const initialState: CounterState = {
value: 0,
};

export const counterSlice = createSlice({
name: "counter",
// `createSlice` will infer the state type from the `initialState` argument
initialState,
reducers: {
increment: (state) => {
state.value += 1;
},
decrement: (state) => {
state.value -= 1;
},
},
});

export const { increment, decrement } = counterSlice.actions;
export default counterSlice.reducer;

Add Redux Provider

In app.tsx, wrap your AppNavigator with the react-redux Provider component

import { Provider } from "react-redux";
import { store } from "./store/store";

...

<Provider store={store}>
<AppNavigator
linking={linking}
initialState={initialNavigationState}
onStateChange={onNavigationStateChange}
/>
</Provider>

Hook up Components

You can now use selectors to grab data and dispatch() to execute actions within your components. Here's an example:

  • Remember to use our exported useAppSelector and useAppDispatch helpers for type safety

WelcomeScreen.tsx

import React, { FC } from "react";
import { View, ViewStyle } from "react-native";
import { Button, Text } from "app/components";
import { AppStackScreenProps } from "../navigators";
import { colors } from "../theme";
import { useSafeAreaInsetsStyle } from "../utils/useSafeAreaInsetsStyle";
import { useAppDispatch, useAppSelector } from "app/store/store";
import { decrement, increment } from "app/store/counterSlice";

interface WelcomeScreenProps extends AppStackScreenProps<"Welcome"> {}

export const WelcomeScreen: FC<WelcomeScreenProps> = () => {
const $containerInsets = useSafeAreaInsetsStyle(["top", "bottom"]);
const count = useAppSelector((state) => state.counter.value);
const dispatch = useAppDispatch();
return (
<View style={[$containerInsets, $container]}>
<Button text="Increment" onPress={() => dispatch(increment())} />
<Button text="Decrement" onPress={() => dispatch(decrement())} />
<Text text={`Count: ${count}`} />
</View>
);
};

const $container: ViewStyle = {
flex: 1,
backgroundColor: colors.background,
};

You're now using Redux!

Persistence

Ignite ships with built-in persistence support for Mobx-State-Tree. We can add similar support for Redux by:

  1. Install redux-persist
yarn add redux-persist
  1. Modify store.ts to include redux-persist

store.ts

import { combineReducers, configureStore } from "@reduxjs/toolkit";
import counterReducer from "./counterSlice";
import { TypedUseSelectorHook, useDispatch, useSelector } from "react-redux";
import {
persistStore,
persistReducer,
FLUSH,
REHYDRATE,
PAUSE,
PERSIST,
PURGE,
REGISTER,
} from "redux-persist";
import AsyncStorage from "@react-native-async-storage/async-storage";

const persistConfig = {
key: "root",
version: 1,
storage: AsyncStorage,
};

const rootReducer = combineReducers({
counter: counterReducer,
});

const persistedReducer = persistReducer(persistConfig, rootReducer);

export const store = configureStore({
reducer: persistedReducer,
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware({
serializableCheck: {
ignoredActions: [FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER],
},
}),
});

export const persistor = persistStore(store);

// Infer the `RootState` and `AppDispatch` types from the store itself
export type RootState = ReturnType<typeof store.getState>;
export type AppDispatch = typeof store.dispatch;

// Use throughout app instead of plain `useDispatch` and `useSelector` for type safety
type DispatchFunc = () => AppDispatch;
export const useAppDispatch: DispatchFunc = useDispatch;
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector;
  1. Add a PersistGate to app.tsx and replace any existing hideSplashScreen calls with the onBeforeLift callback

app.tsx

...

import { persistor, store } from "./store/store"
import { PersistGate } from "redux-persist/integration/react"

...

function App(props: AppProps) {
const { hideSplashScreen } = props
...
const onBeforeLiftPersistGate = () => {
// If your initialization scripts run very fast, it's good to show the splash screen for just a bit longer to prevent flicker.
// Slightly delaying splash screen hiding for better UX; can be customized or removed as needed,
// Note: (vanilla Android) The splash-screen will not appear if you launch your app via the terminal or Android Studio. Kill the app and launch it normally by tapping on the launcher icon. https://stackoverflow.com/a/69831106
// Note: (vanilla iOS) You might notice the splash-screen logo change size. This happens in debug/development mode. Try building the app for release.
setTimeout(hideSplashScreen, 500)
}
...
return (
<SafeAreaProvider initialMetrics={initialWindowMetrics}>
<ErrorBoundary catchErrors={Config.catchErrors}>
<GestureHandlerRootView style={$container}>
<Provider store={store}>
<PersistGate
loading={null}
onBeforeLift={onBeforeLiftPersistGate}
persistor={persistor}
>
<AppNavigator
linking={linking}
initialState={initialNavigationState}
onStateChange={onNavigationStateChange}
/>
</PersistGate>
</Provider>
</GestureHandlerRootView>
</ErrorBoundary>
</SafeAreaProvider>
)
}

export default App

Your Redux state should now be persisted using AsyncStorage!

Reactotron Support

Reactotron has a prebuilt plugin for Redux!

Follow the instructions to install

Is this page still up to date? Did it work for you?

+ + \ No newline at end of file diff --git a/docs/recipes/SampleYAMLCircleCI/index.html b/docs/recipes/SampleYAMLCircleCI/index.html index 1687c72e..98fbb6cc 100644 --- a/docs/recipes/SampleYAMLCircleCI/index.html +++ b/docs/recipes/SampleYAMLCircleCI/index.html @@ -8,8 +8,8 @@ Sample YAML for CircleCi for Ignite | Ignite Cookbook for React Native - - + +
@@ -35,8 +35,8 @@

Have an recipe idea for the cookbook? Contribute your ideas on GitHub!

-

Sample YAML for CircleCi for Ignite

Sampl YAML File

# Javascript Node CircleCI 2.0 configuration file
#
# Check https://circleci.com/docs/2.0/language-javascript/ for more details
#

defaults: &defaults
docker:
# Choose the version of Node you want here
- image: circleci/node:10.11
working_directory: ~/repo

version: 2
jobs:
setup:
<<: *defaults
steps:
- checkout
- restore_cache:
name: Restore node modules
keys:
- v1-dependencies-{{ checksum "package.json" }}
# fallback to using the latest cache if no exact match is found
- v1-dependencies-
- run:
name: Install dependencies
command: |
yarn install
- save_cache:
name: Save node modules
paths:
- node_modules
key: v1-dependencies-{{ checksum "package.json" }}

tests:
<<: *defaults
steps:
- checkout
- restore_cache:
name: Restore node modules
keys:
- v1-dependencies-{{ checksum "package.json" }}
# fallback to using the latest cache if no exact match is found
- v1-dependencies-
- run:
name: Install React Native CLI and Ignite CLI
command: |
sudo npm i -g ignite-cli react-native-cli
- run:
name: Run tests
command: yarn ci:test # this command will be added to/found in your package.json scripts

publish:
<<: *defaults
steps:
- checkout
- run: echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" >> ~/.npmrc
- restore_cache:
name: Restore node modules
keys:
- v1-dependencies-{{ checksum "package.json" }}
# fallback to using the latest cache if no exact match is found
- v1-dependencies-
# Run semantic-release after all the above is set.
- run:
name: Publish to NPM
command: yarn ci:publish # this will be added to your package.json scripts

workflows:
version: 2
test_and_release:
jobs:
- setup
- tests:
requires:
- setup
- publish:
requires:
- tests
filters:
branches:
only: master

Is this page still up to date? Did it work for you?

- - +

Sample YAML for CircleCi for Ignite

Sampl YAML File

# Javascript Node CircleCI 2.0 configuration file
#
# Check https://circleci.com/docs/2.0/language-javascript/ for more details
#

defaults: &defaults
docker:
# Choose the version of Node you want here
- image: circleci/node:10.11
working_directory: ~/repo

version: 2
jobs:
setup:
<<: *defaults
steps:
- checkout
- restore_cache:
name: Restore node modules
keys:
- v1-dependencies-{{ checksum "package.json" }}
# fallback to using the latest cache if no exact match is found
- v1-dependencies-
- run:
name: Install dependencies
command: |
yarn install
- save_cache:
name: Save node modules
paths:
- node_modules
key: v1-dependencies-{{ checksum "package.json" }}

tests:
<<: *defaults
steps:
- checkout
- restore_cache:
name: Restore node modules
keys:
- v1-dependencies-{{ checksum "package.json" }}
# fallback to using the latest cache if no exact match is found
- v1-dependencies-
- run:
name: Install React Native CLI and Ignite CLI
command: |
sudo npm i -g ignite-cli react-native-cli
- run:
name: Run tests
command: yarn ci:test # this command will be added to/found in your package.json scripts

publish:
<<: *defaults
steps:
- checkout
- run: echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" >> ~/.npmrc
- restore_cache:
name: Restore node modules
keys:
- v1-dependencies-{{ checksum "package.json" }}
# fallback to using the latest cache if no exact match is found
- v1-dependencies-
# Run semantic-release after all the above is set.
- run:
name: Publish to NPM
command: yarn ci:publish # this will be added to your package.json scripts

workflows:
version: 2
test_and_release:
jobs:
- setup
- tests:
requires:
- setup
- publish:
requires:
- tests
filters:
branches:
only: master

Is this page still up to date? Did it work for you?

+ + \ No newline at end of file diff --git a/docs/recipes/SelectFieldWithBottomSheet/index.html b/docs/recipes/SelectFieldWithBottomSheet/index.html index 403ac9b9..aa99d201 100644 --- a/docs/recipes/SelectFieldWithBottomSheet/index.html +++ b/docs/recipes/SelectFieldWithBottomSheet/index.html @@ -8,8 +8,8 @@ SelectField using `react-native-bottom-sheet` | Ignite Cookbook for React Native - - + +
@@ -35,8 +35,8 @@

Have an recipe idea for the cookbook? Contribute your ideas on GitHub!

-

SelectField using react-native-bottom-sheet

In this guide, we'll be creating a SelectField component by extending the TextField with a scrollable options View and additional props to handle its customization.

We will be using the react-native-bottom-sheet library for the options list, the ListItem component for displaying individual options, and the TextField component for opening the options list and displaying selected options.

There are many ways you can setup react-native-bottom-sheet to function as a Picker. We'll keep it simple - pressing the TextField will open the options-list. Pressing the option(s) will update the value via callback. You can customize this to fit your usecase.

1. Installation

Let's start by installing the necessary dependencies. You can see complete installation instructions for react-native-bottom-sheet here.

yarn add @gorhom/bottom-sheet@^4

The library requires the react-native-gesture-handler and react-native-reanimated dependencies, but if you're using a newer Ignite boilerplate version, those should already be installed. Just check your package.json file and if you don't see them, follow these steps:

yarn add react-native-reanimated react-native-gesture-handler
# or
expo install react-native-reanimated react-native-gesture-handler

2. Create the SelectField.tsx Component File

Instead of extending the TextField component with more props and functionality, we'll be creating a wrapper for the TextField component that contains additional functionality.

We'll start by creating a new file in the components directory.

touch ./app/components/SelectField.tsx

Let's add some preliminary code to the file. Since the TextInput has its own touch handlers for focus, we'll want to disable that by wrapping it in a View with no pointer-events. The new TouchableOpacity will trigger our options sheet.

import React, { forwardRef, Ref, useImperativeHandle } from "react";
import { View, TouchableOpacity } from "react-native";
import { TextField, TextFieldProps } from "./TextField";

export interface SelectFieldProps
extends Omit<
TextFieldProps,
"ref" | "onValueChange" | "onChange" | "value"
> {}
export interface SelectFieldRef {}

export const SelectField = forwardRef(function SelectField(
props: SelectFieldProps,
ref: Ref<SelectFieldRef>
) {
const { ...TextFieldProps } = props;

const disabled =
TextFieldProps.editable === false || TextFieldProps.status === "disabled";

useImperativeHandle(ref, () => ({}));

return (
<>
<TouchableOpacity activeOpacity={1}>
<View pointerEvents="none">
<TextField {...TextFieldProps} />
</View>
</TouchableOpacity>
</>
);
});
Demo Preview
import { SelectField } from "../components/SelectField";

function FavoriteNBATeamsScreen() {
return (
<SelectField
label="NBA Team(s)"
helper="Select your team(s)"
placeholder="e.g. Trail Blazers"
/>
);
}

yulolimum-capture-2023-02-15--02-34-52

3. Add New Props and Customize the TextField

Now, we can start modifying the code we added in the previous step to support multiple options as well as making the TextField look like a SelectField.

Add a Caret Icon Accessory

Let's add an accessory to the input to make it look like a SelectField.

<TextField
{...TextFieldProps}
RightAccessory={(props) => (
<Icon icon="caretRight" containerStyle={props.style} />
)}
/>

Add Props

The options prop can be any structure that you want (e.g. flat array of values, object where the key is the option value and the value is the label, etc). For our SelectField guide, we'll be doing an array of objects.

We will support multi-select (by default) as well as a single select.

We will override the value prop.

A new renderValue prop can be used to format and display a custom text value. This can be useful when the TextField is not multiline, but your SelectField is.

Additionally, we'll add a new event callback called onSelect since that makes more sense for a SelectField. However, feel free to override TextField's onChange if you prefer.

export interface SelectFieldProps
extends Omit<TextFieldProps, "ref" | "onValueChange" | "onChange"> {
value?: string[];
renderValue?: (value: string[]) => string;
onSelect?: (newValue: string[]) => void;
multiple?: boolean;
options: { label: string; value: string }[];
}

// ...

const {
value = [],
renderValue,
onSelect,
options = [],
multiple = true,
...TextFieldProps
} = props;

Add Logic to Display Selected Options

We'll add some code to display the selected options inside the TextField. This will attempt to use the renderValue formatter function and fallback to a joined string.

const valueString =
renderValue?.(value) ??
value
.map((v) => options.find((o) => o.value === v)?.label)
.filter(Boolean)
.join(", ");

Full Code For This Step

import React, { forwardRef, Ref, useImperativeHandle } from "react";
import { TouchableOpacity, View } from "react-native";
import { Icon } from "./Icon";
import { TextField, TextFieldProps } from "./TextField";

export interface SelectFieldProps
extends Omit<TextFieldProps, "ref" | "onValueChange" | "onChange" | "value"> {
value?: string[];
renderValue?: (value: string[]) => string;
onSelect?: (newValue: string[]) => void;
multiple?: boolean;
options: { label: string; value: string }[];
}
export interface SelectFieldRef {}

export const SelectField = forwardRef(function SelectField(
props: SelectFieldProps,
ref: Ref<SelectFieldRef>
) {
const {
value = [],
onSelect,
renderValue,
options = [],
multiple = true,
...TextFieldProps
} = props;

const disabled =
TextFieldProps.editable === false || TextFieldProps.status === "disabled";

useImperativeHandle(ref, () => ({}));

const valueString =
renderValue?.(value) ??
value
.map((v) => options.find((o) => o.value === v)?.label)
.filter(Boolean)
.join(", ");

return (
<>
<TouchableOpacity activeOpacity={1}>
<View pointerEvents="none">
<TextField
{...TextFieldProps}
value={valueString}
RightAccessory={(props) => (
<Icon icon="caretRight" containerStyle={props.style} />
)}
/>
</View>
</TouchableOpacity>
</>
);
});
Demo Preview
import { SelectField } from "../components/SelectField";

const teams = [
{ label: "Hawks", value: "ATL" },
{ label: "Celtics", value: "BOS" },
// ...
{ label: "Jazz", value: "UTA" },
{ label: "Wizards", value: "WAS" },
];

// prettier-ignore
function FavoriteNBATeamsScreen() {
return (
<>
<SelectField
label="NBA Team(s)"
helper="Select your team(s)"
placeholder="e.g. Trail Blazers"
value={["POR", "MEM", "NOP", "CHI", "CLE", "SAS", "MIL", "LAL", "PHX", "WAS"]}
options={teams}
containerStyle={{ marginBottom: spacing.large }}
/>

<SelectField
label="NBA Team(s)"
helper="Select your team(s)"
placeholder="e.g. Trail Blazers"
value={["POR", "MEM", "NOP", "CHI", "CLE", "SAS", "MIL", "LAL", "PHX", "WAS"]}
options={teams}
containerStyle={{ marginBottom: spacing.large }}
multiline
/>

<SelectField
label="NBA Team(s)"
helper="Select your team(s)"
placeholder="e.g. Trail Blazers"
value={["POR", "MEM", "NOP", "CHI", "CLE", "SAS", "MIL", "LAL", "PHX", "WAS"]}
options={teams}
containerStyle={{ marginBottom: spacing.large }}
renderValue={(value) => `Selected ${value.length} Teams`}
/>
</>
)
}

yulolimum-capture-2023-02-15--03-07-33

4. Add the Sheet Components

In this step, we'll be adding the BottomSheetModal and related components and setting up the touch-events to show/hide it.

Add the BottomSheetModalProvider

Since we will be using the BottomSheetModal component instead of BottomSheet, we will need to add a provider to your entry file.

./app/app.tsx
//...
import { BottomSheetModalProvider } from "@gorhom/bottom-sheet";

//...

return (
<SafeAreaProvider initialMetrics={initialWindowMetrics}>
<ErrorBoundary catchErrors={Config.catchErrors}>
<BottomSheetModalProvider>
<AppNavigator
linking={linking}
initialState={initialNavigationState}
onStateChange={onNavigationStateChange}
/>
</BottomSheetModalProvider>
</ErrorBoundary>
</SafeAreaProvider>
);

//...

Add the Necessary Components to SelectField

Now we will add the UI components that will display our options. This will be a basic example and can be customized as needed.

import {
BottomSheetBackdrop,
BottomSheetFlatList,
BottomSheetFooter,
BottomSheetModal,
} from "@gorhom/bottom-sheet";
import React, { forwardRef, Ref, useImperativeHandle, useRef } from "react";
import { TouchableOpacity, View, ViewStyle } from "react-native";
import { useSafeAreaInsets } from "react-native-safe-area-context";
import { spacing } from "../theme";
import { Button } from "./Button";
import { Icon } from "./Icon";
import { ListItem } from "./ListItem";
import { TextField, TextFieldProps } from "./TextField";

export interface SelectFieldProps
extends Omit<TextFieldProps, "ref" | "onValueChange" | "onChange" | "value"> {
value?: string[];
renderValue?: (value: string[]) => string;
onSelect?: (newValue: string[]) => void;
multiple?: boolean;
options: { label: string; value: string }[];
}
export interface SelectFieldRef {
presentOptions: () => void;
dismissOptions: () => void;
}

export const SelectField = forwardRef(function SelectField(
props: SelectFieldProps,
ref: Ref<SelectFieldRef>
) {
const {
value = [],
onSelect,
renderValue,
options = [],
multiple = true,
...TextFieldProps
} = props;
const sheet = useRef<BottomSheetModal>(null);
const { bottom } = useSafeAreaInsets();

const disabled =
TextFieldProps.editable === false || TextFieldProps.status === "disabled";

useImperativeHandle(ref, () => ({ presentOptions, dismissOptions }));

const valueString =
renderValue?.(value) ??
value
.map((v) => options.find((o) => o.value === v)?.label)
.filter(Boolean)
.join(", ");

function presentOptions() {
if (disabled) return;
sheet.current?.present();
}

function dismissOptions() {
sheet.current?.dismiss();
}

return (
<>
<TouchableOpacity
activeOpacity={1}
onPress={presentOptions}
>
<View pointerEvents="none">
<TextField
{...TextFieldProps}
value={valueString}
RightAccessory={(props) => (
<Icon icon="caretRight" containerStyle={props.style} />
)}
/>
</View>
</TouchableOpacity>

<BottomSheetModal
ref={sheet}
snapPoints={["50%"]}
stackBehavior="replace"
enableDismissOnClose
backdropComponent={(props) => (
<BottomSheetBackdrop
{...props}
appearsOnIndex={0}
disappearsOnIndex={-1}
/>
)}
footerComponent={
!multiple
? undefined
: (props) => (
<BottomSheetFooter
{...props}
style={$bottomSheetFooter}
bottomInset={bottom}
>
<Button
text="Dismiss"
preset="reversed"
onPress={dismissOptions}
/>
</BottomSheetFooter>
)
}
>
<BottomSheetFlatList
style={{ marginBottom: bottom + (multiple ? 56 : 0) }}
data={options}
keyExtractor={(o) => o.value}
renderItem={({ item, index }) => (
<ListItem
text={item.label}
topSeparator={index !== 0}
style={$listItem}
/>
)}
/>
</BottomSheetModal>
</>
);
});

const $bottomSheetFooter: ViewStyle = {
paddingHorizontal: spacing.large,
};

const $listItem: ViewStyle = {
paddingHorizontal: spacing.large,
};
Demo Preview

yulolimum-capture-2023-02-15--04-38-11

5. Add Selected State to Options and Hook Up Callback

The last step is to add the selected state to our options inside the sheet as well as hook up the callback to change the value.

import {
BottomSheetBackdrop,
BottomSheetFlatList,
BottomSheetFooter,
BottomSheetModal,
} from "@gorhom/bottom-sheet";
import React, { forwardRef, Ref, useImperativeHandle, useRef } from "react";
import { TouchableOpacity, View, ViewStyle } from "react-native";
import { useSafeAreaInsets } from "react-native-safe-area-context";
import { colors, spacing } from "../theme";
import { Button } from "./Button";
import { Icon } from "./Icon";
import { ListItem } from "./ListItem";
import { TextField, TextFieldProps } from "./TextField";

export interface SelectFieldProps
extends Omit<TextFieldProps, "ref" | "onValueChange" | "onChange" | "value"> {
value?: string[];
renderValue?: (value: string[]) => string;
onSelect?: (newValue: string[]) => void;
multiple?: boolean;
options: { label: string; value: string }[];
}
export interface SelectFieldRef {
presentOptions: () => void;
dismissOptions: () => void;
}

function without<T>(array: T[], value: T) {
return array.filter((v) => v !== value);
}

export const SelectField = forwardRef(function SelectField(
props: SelectFieldProps,
ref: Ref<SelectFieldRef>
) {
const {
value = [],
onSelect,
renderValue,
options = [],
multiple = true,
...TextFieldProps
} = props;
const sheet = useRef<BottomSheetModal>(null);
const { bottom } = useSafeAreaInsets();

const disabled =
TextFieldProps.editable === false || TextFieldProps.status === "disabled";

useImperativeHandle(ref, () => ({ presentOptions, dismissOptions }));

const valueString =
renderValue?.(value) ??
value
.map((v) => options.find((o) => o.value === v)?.label)
.filter(Boolean)
.join(", ");

function presentOptions() {
if (disabled) return;

sheet.current?.present();
}

function dismissOptions() {
sheet.current?.dismiss();
}

function updateValue(optionValue: string) {
if (value.includes(optionValue)) {
onSelect?.(multiple ? without(value, optionValue) : []);
} else {
onSelect?.(multiple ? [...value, optionValue] : [optionValue]);
if (!multiple) dismissOptions();
}
}

return (
<>
<TouchableOpacity activeOpacity={1} onPress={presentOptions}>
<View pointerEvents="none">
<TextField
{...TextFieldProps}
value={valueString}
RightAccessory={(props) => (
<Icon icon="caretRight" containerStyle={props.style} />
)}
/>
</View>
</TouchableOpacity>

<BottomSheetModal
ref={sheet}
snapPoints={["50%"]}
stackBehavior="replace"
enableDismissOnClose
backdropComponent={(props) => (
<BottomSheetBackdrop
{...props}
appearsOnIndex={0}
disappearsOnIndex={-1}
/>
)}
footerComponent={
!multiple
? undefined
: (props) => (
<BottomSheetFooter
{...props}
style={$bottomSheetFooter}
bottomInset={bottom}
>
<Button
text="Dismiss"
preset="reversed"
onPress={dismissOptions}
/>
</BottomSheetFooter>
)
}
>
<BottomSheetFlatList
style={{ marginBottom: bottom + (multiple ? 56 : 0) }}
data={options}
keyExtractor={(o) => o.value}
renderItem={({ item, index }) => (
<ListItem
text={item.label}
topSeparator={index !== 0}
style={$listItem}
rightIcon={value.includes(item.value) ? "check" : undefined}
rightIconColor={colors.palette.angry500}
onPress={() => updateValue(item.value)}
/>
)}
/>
</BottomSheetModal>
</>
);
});

const $bottomSheetFooter: ViewStyle = {
paddingHorizontal: spacing.large,
};

const $listItem: ViewStyle = {
paddingHorizontal: spacing.large,
};

And we're done!

Demo Preview
import { SelectField } from "../components/SelectField";

const teams = [
{ label: "Hawks", value: "ATL" },
{ label: "Celtics", value: "BOS" },
// ...
{ label: "Jazz", value: "UTA" },
{ label: "Wizards", value: "WAS" },
];

function FavoriteNBATeamsScreen() {
const [selectedTeam, setSelectedTeam] = useState<string[]>([]);
const [selectedTeams, setSelectedTeams] = useState<string[]>([]);

return (
<>
<SelectField
label="NBA Team(s)"
helper="Select your team(s)"
placeholder="e.g. Trail Blazers"
value={selectedTeam}
onSelect={setSelectedTeam}
options={teams}
multiple={false}
containerStyle={{ marginBottom: spacing.large }}
/>

<SelectField
label="NBA Team(s)"
helper="Select your team(s)"
placeholder="e.g. Trail Blazers"
value={selectedTeams}
onSelect={setSelectedTeams}
options={teams}
containerStyle={{ marginBottom: spacing.large }}
renderValue={(value) => `Selected ${value.length} Teams`}
/>
</>
);
}

yulolimum-capture-2023-02-15--05-11-11

Is this page still up to date? Did it work for you?

- - +

SelectField using react-native-bottom-sheet

In this guide, we'll be creating a SelectField component by extending the TextField with a scrollable options View and additional props to handle its customization.

We will be using the react-native-bottom-sheet library for the options list, the ListItem component for displaying individual options, and the TextField component for opening the options list and displaying selected options.

There are many ways you can setup react-native-bottom-sheet to function as a Picker. We'll keep it simple - pressing the TextField will open the options-list. Pressing the option(s) will update the value via callback. You can customize this to fit your usecase.

1. Installation

Let's start by installing the necessary dependencies. You can see complete installation instructions for react-native-bottom-sheet here.

yarn add @gorhom/bottom-sheet@^4

The library requires the react-native-gesture-handler and react-native-reanimated dependencies, but if you're using a newer Ignite boilerplate version, those should already be installed. Just check your package.json file and if you don't see them, follow these steps:

yarn add react-native-reanimated react-native-gesture-handler
# or
expo install react-native-reanimated react-native-gesture-handler

2. Create the SelectField.tsx Component File

Instead of extending the TextField component with more props and functionality, we'll be creating a wrapper for the TextField component that contains additional functionality.

We'll start by creating a new file in the components directory.

touch ./app/components/SelectField.tsx

Let's add some preliminary code to the file. Since the TextInput has its own touch handlers for focus, we'll want to disable that by wrapping it in a View with no pointer-events. The new TouchableOpacity will trigger our options sheet.

import React, { forwardRef, Ref, useImperativeHandle } from "react";
import { View, TouchableOpacity } from "react-native";
import { TextField, TextFieldProps } from "./TextField";

export interface SelectFieldProps
extends Omit<
TextFieldProps,
"ref" | "onValueChange" | "onChange" | "value"
> {}
export interface SelectFieldRef {}

export const SelectField = forwardRef(function SelectField(
props: SelectFieldProps,
ref: Ref<SelectFieldRef>
) {
const { ...TextFieldProps } = props;

const disabled =
TextFieldProps.editable === false || TextFieldProps.status === "disabled";

useImperativeHandle(ref, () => ({}));

return (
<>
<TouchableOpacity activeOpacity={1}>
<View pointerEvents="none">
<TextField {...TextFieldProps} />
</View>
</TouchableOpacity>
</>
);
});
Demo Preview
import { SelectField } from "../components/SelectField";

function FavoriteNBATeamsScreen() {
return (
<SelectField
label="NBA Team(s)"
helper="Select your team(s)"
placeholder="e.g. Trail Blazers"
/>
);
}

yulolimum-capture-2023-02-15--02-34-52

3. Add New Props and Customize the TextField

Now, we can start modifying the code we added in the previous step to support multiple options as well as making the TextField look like a SelectField.

Add a Caret Icon Accessory

Let's add an accessory to the input to make it look like a SelectField.

<TextField
{...TextFieldProps}
RightAccessory={(props) => (
<Icon icon="caretRight" containerStyle={props.style} />
)}
/>

Add Props

The options prop can be any structure that you want (e.g. flat array of values, object where the key is the option value and the value is the label, etc). For our SelectField guide, we'll be doing an array of objects.

We will support multi-select (by default) as well as a single select.

We will override the value prop.

A new renderValue prop can be used to format and display a custom text value. This can be useful when the TextField is not multiline, but your SelectField is.

Additionally, we'll add a new event callback called onSelect since that makes more sense for a SelectField. However, feel free to override TextField's onChange if you prefer.

export interface SelectFieldProps
extends Omit<TextFieldProps, "ref" | "onValueChange" | "onChange"> {
value?: string[];
renderValue?: (value: string[]) => string;
onSelect?: (newValue: string[]) => void;
multiple?: boolean;
options: { label: string; value: string }[];
}

// ...

const {
value = [],
renderValue,
onSelect,
options = [],
multiple = true,
...TextFieldProps
} = props;

Add Logic to Display Selected Options

We'll add some code to display the selected options inside the TextField. This will attempt to use the renderValue formatter function and fallback to a joined string.

const valueString =
renderValue?.(value) ??
value
.map((v) => options.find((o) => o.value === v)?.label)
.filter(Boolean)
.join(", ");

Full Code For This Step

import React, { forwardRef, Ref, useImperativeHandle } from "react";
import { TouchableOpacity, View } from "react-native";
import { Icon } from "./Icon";
import { TextField, TextFieldProps } from "./TextField";

export interface SelectFieldProps
extends Omit<TextFieldProps, "ref" | "onValueChange" | "onChange" | "value"> {
value?: string[];
renderValue?: (value: string[]) => string;
onSelect?: (newValue: string[]) => void;
multiple?: boolean;
options: { label: string; value: string }[];
}
export interface SelectFieldRef {}

export const SelectField = forwardRef(function SelectField(
props: SelectFieldProps,
ref: Ref<SelectFieldRef>
) {
const {
value = [],
onSelect,
renderValue,
options = [],
multiple = true,
...TextFieldProps
} = props;

const disabled =
TextFieldProps.editable === false || TextFieldProps.status === "disabled";

useImperativeHandle(ref, () => ({}));

const valueString =
renderValue?.(value) ??
value
.map((v) => options.find((o) => o.value === v)?.label)
.filter(Boolean)
.join(", ");

return (
<>
<TouchableOpacity activeOpacity={1}>
<View pointerEvents="none">
<TextField
{...TextFieldProps}
value={valueString}
RightAccessory={(props) => (
<Icon icon="caretRight" containerStyle={props.style} />
)}
/>
</View>
</TouchableOpacity>
</>
);
});
Demo Preview
import { SelectField } from "../components/SelectField";

const teams = [
{ label: "Hawks", value: "ATL" },
{ label: "Celtics", value: "BOS" },
// ...
{ label: "Jazz", value: "UTA" },
{ label: "Wizards", value: "WAS" },
];

// prettier-ignore
function FavoriteNBATeamsScreen() {
return (
<>
<SelectField
label="NBA Team(s)"
helper="Select your team(s)"
placeholder="e.g. Trail Blazers"
value={["POR", "MEM", "NOP", "CHI", "CLE", "SAS", "MIL", "LAL", "PHX", "WAS"]}
options={teams}
containerStyle={{ marginBottom: spacing.large }}
/>

<SelectField
label="NBA Team(s)"
helper="Select your team(s)"
placeholder="e.g. Trail Blazers"
value={["POR", "MEM", "NOP", "CHI", "CLE", "SAS", "MIL", "LAL", "PHX", "WAS"]}
options={teams}
containerStyle={{ marginBottom: spacing.large }}
multiline
/>

<SelectField
label="NBA Team(s)"
helper="Select your team(s)"
placeholder="e.g. Trail Blazers"
value={["POR", "MEM", "NOP", "CHI", "CLE", "SAS", "MIL", "LAL", "PHX", "WAS"]}
options={teams}
containerStyle={{ marginBottom: spacing.large }}
renderValue={(value) => `Selected ${value.length} Teams`}
/>
</>
)
}

yulolimum-capture-2023-02-15--03-07-33

4. Add the Sheet Components

In this step, we'll be adding the BottomSheetModal and related components and setting up the touch-events to show/hide it.

Add the BottomSheetModalProvider

Since we will be using the BottomSheetModal component instead of BottomSheet, we will need to add a provider to your entry file.

./app/app.tsx
//...
import { BottomSheetModalProvider } from "@gorhom/bottom-sheet";

//...

return (
<SafeAreaProvider initialMetrics={initialWindowMetrics}>
<ErrorBoundary catchErrors={Config.catchErrors}>
<BottomSheetModalProvider>
<AppNavigator
linking={linking}
initialState={initialNavigationState}
onStateChange={onNavigationStateChange}
/>
</BottomSheetModalProvider>
</ErrorBoundary>
</SafeAreaProvider>
);

//...

Add the Necessary Components to SelectField

Now we will add the UI components that will display our options. This will be a basic example and can be customized as needed.

import {
BottomSheetBackdrop,
BottomSheetFlatList,
BottomSheetFooter,
BottomSheetModal,
} from "@gorhom/bottom-sheet";
import React, { forwardRef, Ref, useImperativeHandle, useRef } from "react";
import { TouchableOpacity, View, ViewStyle } from "react-native";
import { useSafeAreaInsets } from "react-native-safe-area-context";
import { spacing } from "../theme";
import { Button } from "./Button";
import { Icon } from "./Icon";
import { ListItem } from "./ListItem";
import { TextField, TextFieldProps } from "./TextField";

export interface SelectFieldProps
extends Omit<TextFieldProps, "ref" | "onValueChange" | "onChange" | "value"> {
value?: string[];
renderValue?: (value: string[]) => string;
onSelect?: (newValue: string[]) => void;
multiple?: boolean;
options: { label: string; value: string }[];
}
export interface SelectFieldRef {
presentOptions: () => void;
dismissOptions: () => void;
}

export const SelectField = forwardRef(function SelectField(
props: SelectFieldProps,
ref: Ref<SelectFieldRef>
) {
const {
value = [],
onSelect,
renderValue,
options = [],
multiple = true,
...TextFieldProps
} = props;
const sheet = useRef<BottomSheetModal>(null);
const { bottom } = useSafeAreaInsets();

const disabled =
TextFieldProps.editable === false || TextFieldProps.status === "disabled";

useImperativeHandle(ref, () => ({ presentOptions, dismissOptions }));

const valueString =
renderValue?.(value) ??
value
.map((v) => options.find((o) => o.value === v)?.label)
.filter(Boolean)
.join(", ");

function presentOptions() {
if (disabled) return;
sheet.current?.present();
}

function dismissOptions() {
sheet.current?.dismiss();
}

return (
<>
<TouchableOpacity
activeOpacity={1}
onPress={presentOptions}
>
<View pointerEvents="none">
<TextField
{...TextFieldProps}
value={valueString}
RightAccessory={(props) => (
<Icon icon="caretRight" containerStyle={props.style} />
)}
/>
</View>
</TouchableOpacity>

<BottomSheetModal
ref={sheet}
snapPoints={["50%"]}
stackBehavior="replace"
enableDismissOnClose
backdropComponent={(props) => (
<BottomSheetBackdrop
{...props}
appearsOnIndex={0}
disappearsOnIndex={-1}
/>
)}
footerComponent={
!multiple
? undefined
: (props) => (
<BottomSheetFooter
{...props}
style={$bottomSheetFooter}
bottomInset={bottom}
>
<Button
text="Dismiss"
preset="reversed"
onPress={dismissOptions}
/>
</BottomSheetFooter>
)
}
>
<BottomSheetFlatList
style={{ marginBottom: bottom + (multiple ? 56 : 0) }}
data={options}
keyExtractor={(o) => o.value}
renderItem={({ item, index }) => (
<ListItem
text={item.label}
topSeparator={index !== 0}
style={$listItem}
/>
)}
/>
</BottomSheetModal>
</>
);
});

const $bottomSheetFooter: ViewStyle = {
paddingHorizontal: spacing.large,
};

const $listItem: ViewStyle = {
paddingHorizontal: spacing.large,
};
Demo Preview

yulolimum-capture-2023-02-15--04-38-11

5. Add Selected State to Options and Hook Up Callback

The last step is to add the selected state to our options inside the sheet as well as hook up the callback to change the value.

import {
BottomSheetBackdrop,
BottomSheetFlatList,
BottomSheetFooter,
BottomSheetModal,
} from "@gorhom/bottom-sheet";
import React, { forwardRef, Ref, useImperativeHandle, useRef } from "react";
import { TouchableOpacity, View, ViewStyle } from "react-native";
import { useSafeAreaInsets } from "react-native-safe-area-context";
import { colors, spacing } from "../theme";
import { Button } from "./Button";
import { Icon } from "./Icon";
import { ListItem } from "./ListItem";
import { TextField, TextFieldProps } from "./TextField";

export interface SelectFieldProps
extends Omit<TextFieldProps, "ref" | "onValueChange" | "onChange" | "value"> {
value?: string[];
renderValue?: (value: string[]) => string;
onSelect?: (newValue: string[]) => void;
multiple?: boolean;
options: { label: string; value: string }[];
}
export interface SelectFieldRef {
presentOptions: () => void;
dismissOptions: () => void;
}

function without<T>(array: T[], value: T) {
return array.filter((v) => v !== value);
}

export const SelectField = forwardRef(function SelectField(
props: SelectFieldProps,
ref: Ref<SelectFieldRef>
) {
const {
value = [],
onSelect,
renderValue,
options = [],
multiple = true,
...TextFieldProps
} = props;
const sheet = useRef<BottomSheetModal>(null);
const { bottom } = useSafeAreaInsets();

const disabled =
TextFieldProps.editable === false || TextFieldProps.status === "disabled";

useImperativeHandle(ref, () => ({ presentOptions, dismissOptions }));

const valueString =
renderValue?.(value) ??
value
.map((v) => options.find((o) => o.value === v)?.label)
.filter(Boolean)
.join(", ");

function presentOptions() {
if (disabled) return;

sheet.current?.present();
}

function dismissOptions() {
sheet.current?.dismiss();
}

function updateValue(optionValue: string) {
if (value.includes(optionValue)) {
onSelect?.(multiple ? without(value, optionValue) : []);
} else {
onSelect?.(multiple ? [...value, optionValue] : [optionValue]);
if (!multiple) dismissOptions();
}
}

return (
<>
<TouchableOpacity activeOpacity={1} onPress={presentOptions}>
<View pointerEvents="none">
<TextField
{...TextFieldProps}
value={valueString}
RightAccessory={(props) => (
<Icon icon="caretRight" containerStyle={props.style} />
)}
/>
</View>
</TouchableOpacity>

<BottomSheetModal
ref={sheet}
snapPoints={["50%"]}
stackBehavior="replace"
enableDismissOnClose
backdropComponent={(props) => (
<BottomSheetBackdrop
{...props}
appearsOnIndex={0}
disappearsOnIndex={-1}
/>
)}
footerComponent={
!multiple
? undefined
: (props) => (
<BottomSheetFooter
{...props}
style={$bottomSheetFooter}
bottomInset={bottom}
>
<Button
text="Dismiss"
preset="reversed"
onPress={dismissOptions}
/>
</BottomSheetFooter>
)
}
>
<BottomSheetFlatList
style={{ marginBottom: bottom + (multiple ? 56 : 0) }}
data={options}
keyExtractor={(o) => o.value}
renderItem={({ item, index }) => (
<ListItem
text={item.label}
topSeparator={index !== 0}
style={$listItem}
rightIcon={value.includes(item.value) ? "check" : undefined}
rightIconColor={colors.palette.angry500}
onPress={() => updateValue(item.value)}
/>
)}
/>
</BottomSheetModal>
</>
);
});

const $bottomSheetFooter: ViewStyle = {
paddingHorizontal: spacing.large,
};

const $listItem: ViewStyle = {
paddingHorizontal: spacing.large,
};

And we're done!

Demo Preview
import { SelectField } from "../components/SelectField";

const teams = [
{ label: "Hawks", value: "ATL" },
{ label: "Celtics", value: "BOS" },
// ...
{ label: "Jazz", value: "UTA" },
{ label: "Wizards", value: "WAS" },
];

function FavoriteNBATeamsScreen() {
const [selectedTeam, setSelectedTeam] = useState<string[]>([]);
const [selectedTeams, setSelectedTeams] = useState<string[]>([]);

return (
<>
<SelectField
label="NBA Team(s)"
helper="Select your team(s)"
placeholder="e.g. Trail Blazers"
value={selectedTeam}
onSelect={setSelectedTeam}
options={teams}
multiple={false}
containerStyle={{ marginBottom: spacing.large }}
/>

<SelectField
label="NBA Team(s)"
helper="Select your team(s)"
placeholder="e.g. Trail Blazers"
value={selectedTeams}
onSelect={setSelectedTeams}
options={teams}
containerStyle={{ marginBottom: spacing.large }}
renderValue={(value) => `Selected ${value.length} Teams`}
/>
</>
);
}

yulolimum-capture-2023-02-15--05-11-11

Is this page still up to date? Did it work for you?

+ + \ No newline at end of file diff --git a/docs/recipes/StayingWithExpo/index.html b/docs/recipes/StayingWithExpo/index.html index 3ab83775..5d74035d 100644 --- a/docs/recipes/StayingWithExpo/index.html +++ b/docs/recipes/StayingWithExpo/index.html @@ -8,8 +8,8 @@ Staying With Expo | Ignite Cookbook for React Native - - + +
@@ -35,8 +35,8 @@

Have an recipe idea for the cookbook? Contribute your ideas on GitHub!

-

Staying With Expo

This guide will teach you how to set up an Expo development build which prepares your project for native code via Config Plugins, but keeps you in Expo's managed workflow.

Appetizer

Follow the Pristine Expo Project recipe first to make sure you're starting with an Expo only project.

You'll also need eas-cli globally installed and and an Expo account if you don't already have one.

npm install -g eas-cli

Optional: You can use EAS builds for free, however there is a queue time to wait for your build. It is possible to build locally, however you'll need a couple of other dependencies installed for proper iOS and Android builds (if you can already build iOS/Android natively, you're probably good to go!)

iOS
brew install cocoapods fastlane
Android

SDK and NDK

Steps

1. Project Setup

From within your project directory, run the following:

yarn add expo-dev-client

Create or link an EAS project.

eas init
✔ Linked to project @infinitered/cookbook
✔ Linked app.json to project with ID 012aaaa3-4ce5-4bae-9f4d-2f842489f07a

Configure the project to support EAS Build.

eas build:configure

2. Build Profile

Modify the newly generated eas.json to configure a preview build profile

{
"cli": {
"version": ">= 0.60.0"
},
"build": {
"development": {
"developmentClient": true,
"distribution": "internal"
},
"preview": {
"developmentClient": true,
"ios": {
"simulator": true
}
},
"production": {}
},
"submit": {
"production": {}
}
}

3. Run the Build!

Using EAS build servers

eas build --profile preview

Once complete, you can download the Android apk or iOS tar file.

Build Locally

eas build --profile preview --local

Your app will be saved in the root directory unless you specify the desired directory with the environment variable EAS_LOCAL_BUILD_ARTIFACTS_DIR, for example:

EAS_LOCAL_BUILD_ARTIFACTS_DIR=build eas build --profile preview --local

This will save your *.apk or *.tar.gz (containing the .app) in the [project-dir]/build/ directory.

4. Run the Development Client

With the builds complete, let's add them to your emulator or simulator.

iOS
  • tar zxvf build/build-*.tar.gz -C build/ (adapt this command depending on where you saved it to)
  • Drag the PizzaApp.app onto your iOS simulator
Android

Drag the APK onto your emulator or install it on a device (making sure your settings are appropriate for "Install unknown apps")

You can now develop locally like you normally would with Expo Go, with one last adjustment to the start script.

In package.json modify the start script to use the expo-dev-client package.

--"start": "expo start"
++"start": "expo start --dev-client"

Run yarn start in your terminal so metro starts up. Follow the Expo CLI to boot up either the Android or iOS app. You'll notice Expo Go has not launched in this case, but something that looks very similar (you can still shake the device for developer menu, etc).

Is this page still up to date? Did it work for you?

- - +

Staying With Expo

This guide will teach you how to set up an Expo development build which prepares your project for native code via Config Plugins, but keeps you in Expo's managed workflow.

Appetizer

Follow the Pristine Expo Project recipe first to make sure you're starting with an Expo only project.

You'll also need eas-cli globally installed and and an Expo account if you don't already have one.

npm install -g eas-cli

Optional: You can use EAS builds for free, however there is a queue time to wait for your build. It is possible to build locally, however you'll need a couple of other dependencies installed for proper iOS and Android builds (if you can already build iOS/Android natively, you're probably good to go!)

iOS
brew install cocoapods fastlane
Android

SDK and NDK

Steps

1. Project Setup

From within your project directory, run the following:

yarn add expo-dev-client

Create or link an EAS project.

eas init
✔ Linked to project @infinitered/cookbook
✔ Linked app.json to project with ID 012aaaa3-4ce5-4bae-9f4d-2f842489f07a

Configure the project to support EAS Build.

eas build:configure

2. Build Profile

Modify the newly generated eas.json to configure a preview build profile

{
"cli": {
"version": ">= 0.60.0"
},
"build": {
"development": {
"developmentClient": true,
"distribution": "internal"
},
"preview": {
"developmentClient": true,
"ios": {
"simulator": true
}
},
"production": {}
},
"submit": {
"production": {}
}
}

3. Run the Build!

Using EAS build servers

eas build --profile preview

Once complete, you can download the Android apk or iOS tar file.

Build Locally

eas build --profile preview --local

Your app will be saved in the root directory unless you specify the desired directory with the environment variable EAS_LOCAL_BUILD_ARTIFACTS_DIR, for example:

EAS_LOCAL_BUILD_ARTIFACTS_DIR=build eas build --profile preview --local

This will save your *.apk or *.tar.gz (containing the .app) in the [project-dir]/build/ directory.

4. Run the Development Client

With the builds complete, let's add them to your emulator or simulator.

iOS
  • tar zxvf build/build-*.tar.gz -C build/ (adapt this command depending on where you saved it to)
  • Drag the PizzaApp.app onto your iOS simulator
Android

Drag the APK onto your emulator or install it on a device (making sure your settings are appropriate for "Install unknown apps")

You can now develop locally like you normally would with Expo Go, with one last adjustment to the start script.

In package.json modify the start script to use the expo-dev-client package.

--"start": "expo start"
++"start": "expo start --dev-client"

Run yarn start in your terminal so metro starts up. Follow the Expo CLI to boot up either the Android or iOS app. You'll notice Expo Go has not launched in this case, but something that looks very similar (you can still shake the device for developer menu, etc).

Is this page still up to date? Did it work for you?

+ + \ No newline at end of file diff --git a/docs/recipes/SwitchBetweenExpoGoCNG/index.html b/docs/recipes/SwitchBetweenExpoGoCNG/index.html index 3fbbd889..234e402f 100644 --- a/docs/recipes/SwitchBetweenExpoGoCNG/index.html +++ b/docs/recipes/SwitchBetweenExpoGoCNG/index.html @@ -8,8 +8,8 @@ Switch Between Expo Go and Expo CNG | Ignite Cookbook for React Native - - + +
@@ -35,9 +35,9 @@

Have an recipe idea for the cookbook? Contribute your ideas on GitHub!

-

Switch a Project Between Expo Go and Expo CNG

If you created an Ignite project using the Expo Go workflow and you need to transition to Expo CNG (Continuous Native Generation) or visa versa, this guide will teach you how to reconfigure your project.

Expo Go -> Expo CNG

If you started with Expo Go but now need to add a library with native code, create your own custom native code, or modify native project configuration, you'll no longer be able to run your app inside Expo Go.

Thankfully, this is super easy thanks to Expo's Continuous Native Generation! +

Switch a Project Between Expo Go and Expo CNG

If you created an Ignite project using the Expo Go workflow and you need to transition to Expo CNG (Continuous Native Generation) or visa versa, this guide will teach you how to reconfigure your project.

Expo Go -> Expo CNG

If you started with Expo Go but now need to add a library with native code, create your own custom native code, or modify native project configuration, you'll no longer be able to run your app inside Expo Go.

Thankfully, this is super easy thanks to Expo's Continuous Native Generation! We only need to slightly change how we build & run our app.

In package.json, modify scripts:

--"android": "npx expo start --android",
--"ios": "npx expo start --ios",
++"android": "npx expo run:android",
++"ios": "npx expo run:ios",

Expo handles the rest!

When you run npm run ios or npm run android, Expo will generate native projects and create ios and android directories, create a development build, and launch your standalone app. You are now successfully using Expo CNG!

To learn more, check out Expo's documentation on adding custom native code.

Expo CNG -> Expo Go

If you started with Expo CNG workflow, but your app isn't utilizing any custom native functionality and you want to use Expo Go for developing your app, follow these steps!

Important Note: To successfully run your app using Expo Go, your project must not contain any custom native code, project configuration, or native libraries outside of the Expo SDK. Your project also can't contain any expo.plugins inside your app.json. If your app contains native code, libraries, configuration, or plugins and you attempt to run inside Expo Go, expect your app to crash or not function properly.

Steps

  1. In package.json, modify scripts:
--"android": "npx expo run:android",
--"ios": "npx expo run:ios",
++"android": "npx expo start --android",
++"ios": "npx expo start --ios",
  1. Some libraries may need to be downgraded in order to be compatible with Expo Go. In package.json, you may need to downgrade dependencies so they do not exceed the version supported by Expo Go.
"@react-native-async-storage/async-storage": "1.18.2",
"@shopify/flash-list": "1.4.3",
"expo-application": "~5.3.0",
"expo-font": "~11.4.0",
"expo-localization": "~14.3.0",
"react-native": "0.72.6",

Note: View latest values in Ignite - expoGoCompatibility.ts

Is this page still up to date? Did it work for you?

- - + + \ No newline at end of file diff --git a/docs/recipes/TypeScriptBaseURL/index.html b/docs/recipes/TypeScriptBaseURL/index.html index 9d45d9be..bd650649 100644 --- a/docs/recipes/TypeScriptBaseURL/index.html +++ b/docs/recipes/TypeScriptBaseURL/index.html @@ -8,8 +8,8 @@ TypeScript baseUrl Configuration | Ignite Cookbook for React Native - - + +
@@ -35,8 +35,8 @@

Have an recipe idea for the cookbook? Contribute your ideas on GitHub!

-

TypeScript baseUrl Configuration

Overview

Depending on your project structure, sometimes you'll end up with longer relative imports like this:

import { Thing } from "../../../../../components/thing";

We can utilize TypeScript's baseUrl module to help resolve non-absolute module names. Doing so will allow us to change the above to:

import { Thing } from "~/components/thing";

Project Dependencies

yarn add -D babel-plugin-root-import

TypeScript Configuration Changes

Open tsconfig.json and add the baseUrl and path properties:

{
// ...
"baseUrl": "./",
// the following assumes Ignite's app/ structure, however yours may differ
"paths": { "~/*": ["app/*"] }
}

Babel Configuration Changes

Open babel.config.js and add the following plugin array object:

[
"babel-plugin-root-import",
{
root: __dirname,
rootPathPrefix: "~/",
// mapping ~/ to the ./app directory (again, your app structure may differ here)
rootPathSuffix: "app",
},
],

Taste Test in a Component!

Open up ./app/screens/DemoShowroomScreen.tsx and let's update the relative imports from:

import { ListItem, Screen, Text } from "../../components";
import { isRTL } from "../../i18n";
import { DemoTabScreenProps } from "../../navigators/DemoNavigator";
import { colors, spacing } from "../../theme";

to

import { ListItem, Screen, Text } from "~/components";
import { isRTL } from "~/i18n";
import { DemoTabScreenProps } from "~/navigators/DemoNavigator";
import { colors, spacing } from "~/theme";

Fire up the app and make sure everything still works!

yarn expo:start

Note: if you receive an error about not being able to resolve the components, you may have to clear your bundler cache via

yarn expo:start --clear

Resources

Is this page still up to date? Did it work for you?

- - +

TypeScript baseUrl Configuration

Overview

Depending on your project structure, sometimes you'll end up with longer relative imports like this:

import { Thing } from "../../../../../components/thing";

We can utilize TypeScript's baseUrl module to help resolve non-absolute module names. Doing so will allow us to change the above to:

import { Thing } from "~/components/thing";

Project Dependencies

yarn add -D babel-plugin-root-import

TypeScript Configuration Changes

Open tsconfig.json and add the baseUrl and path properties:

{
// ...
"baseUrl": "./",
// the following assumes Ignite's app/ structure, however yours may differ
"paths": { "~/*": ["app/*"] }
}

Babel Configuration Changes

Open babel.config.js and add the following plugin array object:

[
"babel-plugin-root-import",
{
root: __dirname,
rootPathPrefix: "~/",
// mapping ~/ to the ./app directory (again, your app structure may differ here)
rootPathSuffix: "app",
},
],

Taste Test in a Component!

Open up ./app/screens/DemoShowroomScreen.tsx and let's update the relative imports from:

import { ListItem, Screen, Text } from "../../components";
import { isRTL } from "../../i18n";
import { DemoTabScreenProps } from "../../navigators/DemoNavigator";
import { colors, spacing } from "../../theme";

to

import { ListItem, Screen, Text } from "~/components";
import { isRTL } from "~/i18n";
import { DemoTabScreenProps } from "~/navigators/DemoNavigator";
import { colors, spacing } from "~/theme";

Fire up the app and make sure everything still works!

yarn expo:start

Note: if you receive an error about not being able to resolve the components, you may have to clear your bundler cache via

yarn expo:start --clear

Resources

Is this page still up to date? Did it work for you?

+ + \ No newline at end of file diff --git a/docs/recipes/UnrenderedItemInScrollView/index.html b/docs/recipes/UnrenderedItemInScrollView/index.html index 31c226fe..737c6538 100644 --- a/docs/recipes/UnrenderedItemInScrollView/index.html +++ b/docs/recipes/UnrenderedItemInScrollView/index.html @@ -8,8 +8,8 @@ Scrolling to a location that hasn't been rendered using FlatList or SectionList | Ignite Cookbook for React Native - - + +
@@ -35,8 +35,8 @@

Have an recipe idea for the cookbook? Contribute your ideas on GitHub!

-

Scrolling to a location that hasn't been rendered using FlatList or SectionList

Calling scrollViewRef.current.scrollToLocation() on a React Native FlatList or SectionList will fail on occasion because it can't scroll to a location that hasn't been rendered yet.

The solution to this is implementing onScrollToIndexFailed with some sort of recovery functionality to keep trying the scroll. This is a Higher Order Component (HOC) for SectionList that handles this for us.

This component basically tries over and over to scroll to the requested location until it gets it right and no longer calls onScrollToIndexFailed.

import * as React from 'react';
import { SectionList, SectionListProps, SectionListScrollParams } from 'react-native';

interface SectionListHandle {
scrollToLocation: (params: SectionListScrollParams) => void;
}

/**
* This is a wrapper around react-native's SectionList that adds protection against scrolling to an
* unknown (not rendered yet) location. This is useful for cases where the user wants to scroll to a
* position very far down the list but we haven't rendered that far yet.
*
* This adds onScrollToIndexFailed property to SectionList so that if the scroll fails, we calculate the approximate
* scroll position, scroll there, and then try again to get the exact position requested.
*
* Essentially, it's a "guess the position and retry the operation" strategy until the list is scrolled to the
* correct location.
*/
export const ScrollProtectedSectionList = React.forwardRef<
SectionListHandle,
SectionListProps<any, any>
>((props, forwardedRef) => {
const internalRef = React.useRef<SectionList>(null);
const [lastScrollRequest, setLastScrollRequest] = React.useState<SectionListScrollParams>();
const timeout = React.useRef<ReturnType<typeof setTimeout>>();

const onScrollToIndexFailed = (info: {
index: number;
highestMeasuredFrameIndex: number;
averageItemLength: number;
}) => {
console.log('ScrollProtectedSectionList.onScrollToIndexFailed', info);

// Calculate the possible position of the item and scroll there using the internal scroll responder.
const offset = info.averageItemLength * info.index;
internalRef.current?.getScrollResponder()?.scrollTo({ x: 0, y: offset, animated: false });

// If we know exactly where we want to scroll to, we can just scroll now since the item is likely visible.
// Otherwise it'll call this function recursively again.
if (lastScrollRequest) {
timeout.current = setTimeout(() => {
internalRef.current?.scrollToLocation(lastScrollRequest);
}, 100);
}
};

// Clear the timeout if it still exists when the component unmounts.
React.useEffect(() => {
return () => timeout.current && clearTimeout(timeout.current);
}, []);

React.useImperativeHandle(
forwardedRef,
() => ({
scrollToLocation: (params: SectionListScrollParams) => {
internalRef.current?.scrollToLocation(params);
setLastScrollRequest(params);
},
}),
[internalRef],
);

return <SectionList {...props} ref={internalRef} onScrollToIndexFailed={onScrollToIndexFailed} />;
});

Is this page still up to date? Did it work for you?

- - +

Scrolling to a location that hasn't been rendered using FlatList or SectionList

Calling scrollViewRef.current.scrollToLocation() on a React Native FlatList or SectionList will fail on occasion because it can't scroll to a location that hasn't been rendered yet.

The solution to this is implementing onScrollToIndexFailed with some sort of recovery functionality to keep trying the scroll. This is a Higher Order Component (HOC) for SectionList that handles this for us.

This component basically tries over and over to scroll to the requested location until it gets it right and no longer calls onScrollToIndexFailed.

import * as React from 'react';
import { SectionList, SectionListProps, SectionListScrollParams } from 'react-native';

interface SectionListHandle {
scrollToLocation: (params: SectionListScrollParams) => void;
}

/**
* This is a wrapper around react-native's SectionList that adds protection against scrolling to an
* unknown (not rendered yet) location. This is useful for cases where the user wants to scroll to a
* position very far down the list but we haven't rendered that far yet.
*
* This adds onScrollToIndexFailed property to SectionList so that if the scroll fails, we calculate the approximate
* scroll position, scroll there, and then try again to get the exact position requested.
*
* Essentially, it's a "guess the position and retry the operation" strategy until the list is scrolled to the
* correct location.
*/
export const ScrollProtectedSectionList = React.forwardRef<
SectionListHandle,
SectionListProps<any, any>
>((props, forwardedRef) => {
const internalRef = React.useRef<SectionList>(null);
const [lastScrollRequest, setLastScrollRequest] = React.useState<SectionListScrollParams>();
const timeout = React.useRef<ReturnType<typeof setTimeout>>();

const onScrollToIndexFailed = (info: {
index: number;
highestMeasuredFrameIndex: number;
averageItemLength: number;
}) => {
console.log('ScrollProtectedSectionList.onScrollToIndexFailed', info);

// Calculate the possible position of the item and scroll there using the internal scroll responder.
const offset = info.averageItemLength * info.index;
internalRef.current?.getScrollResponder()?.scrollTo({ x: 0, y: offset, animated: false });

// If we know exactly where we want to scroll to, we can just scroll now since the item is likely visible.
// Otherwise it'll call this function recursively again.
if (lastScrollRequest) {
timeout.current = setTimeout(() => {
internalRef.current?.scrollToLocation(lastScrollRequest);
}, 100);
}
};

// Clear the timeout if it still exists when the component unmounts.
React.useEffect(() => {
return () => timeout.current && clearTimeout(timeout.current);
}, []);

React.useImperativeHandle(
forwardedRef,
() => ({
scrollToLocation: (params: SectionListScrollParams) => {
internalRef.current?.scrollToLocation(params);
setLastScrollRequest(params);
},
}),
[internalRef],
);

return <SectionList {...props} ref={internalRef} onScrollToIndexFailed={onScrollToIndexFailed} />;
});

Is this page still up to date? Did it work for you?

+ + \ No newline at end of file diff --git a/docs/recipes/UpdatingDependencies/index.html b/docs/recipes/UpdatingDependencies/index.html index cbbb8c1d..f9344b12 100644 --- a/docs/recipes/UpdatingDependencies/index.html +++ b/docs/recipes/UpdatingDependencies/index.html @@ -8,8 +8,8 @@ Updating Dependencies with Yarn Audit, Outdated and Upgrade | Ignite Cookbook for React Native - - + +
@@ -35,8 +35,8 @@

Have an recipe idea for the cookbook? Contribute your ideas on GitHub!

-

Updating Dependencies with Yarn Audit, Outdated and Upgrade

If you get a bunch of warnings in the git command output about vulnerabilities, similar to this: remote: Github found 80 vulnerabilities on <branch>..., you can examine these vulnerabilities with yarn audit, get a list of outdated packages with yarn outdated, and update each dependency using yarn update

Yarn Audit Checks for known security issues with the installed packages. Issue the command from the root of your project. The output is a list of known issues.

Usage:

yarn audit

yarn audit usage in terminal

Yarn Outdated generates a list of outdated packages and all the info you need to make decisions about updating their versions, such as whether a major update that is NOT backwards compatible is available. A handy link to the repository is provided so you can read about the consequences of updating that dependency in your project.

Usage:

yarn outdated

yarn outdated usage in terminal

Yarn Upgrade updates the version of a given package to the latest, or to a specific version if you specify it. Be sure to provide an argument to this command; otherwise, it will update all dependencies to their latest versions, which is usually not what you want.

Usage:

yarn upgrade-interactive
yarn upgrade-interactive --latest

yarn upgrade-interactive usage in terminal

Is this page still up to date? Did it work for you?

- - +

Updating Dependencies with Yarn Audit, Outdated and Upgrade

If you get a bunch of warnings in the git command output about vulnerabilities, similar to this: remote: Github found 80 vulnerabilities on <branch>..., you can examine these vulnerabilities with yarn audit, get a list of outdated packages with yarn outdated, and update each dependency using yarn update

Yarn Audit Checks for known security issues with the installed packages. Issue the command from the root of your project. The output is a list of known issues.

Usage:

yarn audit

yarn audit usage in terminal

Yarn Outdated generates a list of outdated packages and all the info you need to make decisions about updating their versions, such as whether a major update that is NOT backwards compatible is available. A handy link to the repository is provided so you can read about the consequences of updating that dependency in your project.

Usage:

yarn outdated

yarn outdated usage in terminal

Yarn Upgrade updates the version of a given package to the latest, or to a specific version if you specify it. Be sure to provide an argument to this command; otherwise, it will update all dependencies to their latest versions, which is usually not what you want.

Usage:

yarn upgrade-interactive
yarn upgrade-interactive --latest

yarn upgrade-interactive usage in terminal

Is this page still up to date? Did it work for you?

+ + \ No newline at end of file diff --git a/docs/recipes/UsingScreenReaders/index.html b/docs/recipes/UsingScreenReaders/index.html index 95a5b3ea..057e5609 100644 --- a/docs/recipes/UsingScreenReaders/index.html +++ b/docs/recipes/UsingScreenReaders/index.html @@ -8,8 +8,8 @@ Using Screen Readers | Ignite Cookbook for React Native - - + +
@@ -35,7 +35,7 @@

Have an recipe idea for the cookbook? Contribute your ideas on GitHub!

-

Using Screen Readers

iOS

On a simulator

Setting it up +

Using Screen Readers

iOS

On a simulator

Setting it up Simulators don't have VoiceOver, so you'll have to use the Accessibility Inspector.

From XCode, go to Xcode menu > Developer Tools > Accessibility Inspector, and make sure to change the laptop icon in the top left of the inspector window to the simulator instead.

Operation For operation, the WWDC video on the inspector is more helpful than the documentation: https://developer.apple.com/videos/play/wwdc2019/257/.

On a device

Setting it up Go to Settings > Accessibility > VoiceOver and toggle VoiceOver on. @@ -50,7 +50,7 @@ TODO: Voice Assistant instructions

You can also probably install TalkBack on your device. Install "Android Accessibility Suite" from the Play store, and then enable it from Settings > Accessibility > Installed Accessibility Services. Note that if you have multiple profiles on this device, this service must be installed on the primary (personal) profile.

Operation Cheatsheet: https://dequeuniversity.com/screenreaders/talkback-shortcuts

Is this page still up to date? Did it work for you?

- - + + \ No newline at end of file diff --git a/docs/tags/accessibility/index.html b/docs/tags/accessibility/index.html index 2127ed67..1595be13 100644 --- a/docs/tags/accessibility/index.html +++ b/docs/tags/accessibility/index.html @@ -8,8 +8,8 @@ 3 docs tagged with "Accessibility" | Ignite Cookbook for React Native - - + +
@@ -36,7 +36,7 @@

3 docs tagged with "Accessibility"

View All Tags
- - + + \ No newline at end of file diff --git a/docs/tags/android/index.html b/docs/tags/android/index.html index 129ce79a..18ba113c 100644 --- a/docs/tags/android/index.html +++ b/docs/tags/android/index.html @@ -8,8 +8,8 @@ 3 docs tagged with "Android" | Ignite Cookbook for React Native - - + +
@@ -36,7 +36,7 @@

3 docs tagged with "Android"

View All Tags
- - + + \ No newline at end of file diff --git a/docs/tags/apisauce/index.html b/docs/tags/apisauce/index.html index 5fe17901..62b184fb 100644 --- a/docs/tags/apisauce/index.html +++ b/docs/tags/apisauce/index.html @@ -8,8 +8,8 @@ One doc tagged with "Apisauce" | Ignite Cookbook for React Native - - + +
@@ -36,7 +36,7 @@

One doc tagged with "Apisauce"

View All Tags
- - + + \ No newline at end of file diff --git a/docs/tags/async-storage/index.html b/docs/tags/async-storage/index.html index 203148fe..500dbd99 100644 --- a/docs/tags/async-storage/index.html +++ b/docs/tags/async-storage/index.html @@ -8,8 +8,8 @@ One doc tagged with "AsyncStorage" | Ignite Cookbook for React Native - - + +
@@ -36,7 +36,7 @@

One doc tagged with "AsyncStorage"

View All Tags
- - + + \ No newline at end of file diff --git a/docs/tags/authentication/index.html b/docs/tags/authentication/index.html index 69d340e5..2f045411 100644 --- a/docs/tags/authentication/index.html +++ b/docs/tags/authentication/index.html @@ -8,8 +8,8 @@ One doc tagged with "Authentication" | Ignite Cookbook for React Native - - + +
@@ -36,7 +36,7 @@

One doc tagged with "Authentication"

View All Tags
- - + + \ No newline at end of file diff --git a/docs/tags/babel/index.html b/docs/tags/babel/index.html index d66ce431..b1a779eb 100644 --- a/docs/tags/babel/index.html +++ b/docs/tags/babel/index.html @@ -8,8 +8,8 @@ One doc tagged with "Babel" | Ignite Cookbook for React Native - - + +
@@ -36,7 +36,7 @@

One doc tagged with "Babel"

View All Tags
- - + + \ No newline at end of file diff --git a/docs/tags/ci-cd/index.html b/docs/tags/ci-cd/index.html index d2e1d35f..2917cb4d 100644 --- a/docs/tags/ci-cd/index.html +++ b/docs/tags/ci-cd/index.html @@ -8,8 +8,8 @@ 2 docs tagged with "CI/CD" | Ignite Cookbook for React Native - - + +
@@ -36,7 +36,7 @@

2 docs tagged with "CI/CD"

View All Tags
- - + + \ No newline at end of file diff --git a/docs/tags/debug/index.html b/docs/tags/debug/index.html index a91ecbef..bbdc4ed5 100644 --- a/docs/tags/debug/index.html +++ b/docs/tags/debug/index.html @@ -8,8 +8,8 @@ One doc tagged with "Debug" | Ignite Cookbook for React Native - - + +
@@ -36,7 +36,7 @@

One doc tagged with "Debug"

View All Tags
- - + + \ No newline at end of file diff --git a/docs/tags/dependencies/index.html b/docs/tags/dependencies/index.html index 533ef8ab..ab21e80d 100644 --- a/docs/tags/dependencies/index.html +++ b/docs/tags/dependencies/index.html @@ -8,8 +8,8 @@ One doc tagged with "Dependencies" | Ignite Cookbook for React Native - - + +
@@ -36,7 +36,7 @@

One doc tagged with "Dependencies"

View All Tags

Updating Dependencies with Yarn Audit, Outdated and Upgrade

If you get a bunch of warnings in the git command output about vulnerabilities, similar to this Github found 80 vulnerabilities on ..., you can examine these vulnerabilities with yarn audit, get a list of outdated packages with yarn outdated, and update each dependency using yarn update

- - + + \ No newline at end of file diff --git a/docs/tags/eas-update/index.html b/docs/tags/eas-update/index.html index 21c9ca83..53663d33 100644 --- a/docs/tags/eas-update/index.html +++ b/docs/tags/eas-update/index.html @@ -8,8 +8,8 @@ One doc tagged with "EAS Update" | Ignite Cookbook for React Native - - + +
@@ -36,7 +36,7 @@

One doc tagged with "EAS Update"

View All Tags

EAS Update

Setting up Ignite to deploy over-the-air (OTA) updates via EAS

- - + + \ No newline at end of file diff --git a/docs/tags/environment-variables/index.html b/docs/tags/environment-variables/index.html index e751377d..2efeacd1 100644 --- a/docs/tags/environment-variables/index.html +++ b/docs/tags/environment-variables/index.html @@ -8,8 +8,8 @@ One doc tagged with "Environment Variables" | Ignite Cookbook for React Native - - + +
@@ -36,7 +36,7 @@

One doc tagged with "Environment Variables"

View All Tags
- - + + \ No newline at end of file diff --git a/docs/tags/expo-dev-client/index.html b/docs/tags/expo-dev-client/index.html index 16407c28..5c18ecec 100644 --- a/docs/tags/expo-dev-client/index.html +++ b/docs/tags/expo-dev-client/index.html @@ -8,8 +8,8 @@ One doc tagged with "expo-dev-client" | Ignite Cookbook for React Native - - + +
@@ -36,7 +36,7 @@

One doc tagged with "expo-dev-client"

View All Tags

Staying With Expo

Setting up Ignite to build a custom Expo development client for use with Config Plugins

- - + + \ No newline at end of file diff --git a/docs/tags/expo-router/index.html b/docs/tags/expo-router/index.html new file mode 100644 index 00000000..296e9dca --- /dev/null +++ b/docs/tags/expo-router/index.html @@ -0,0 +1,42 @@ + + + + + + + + + +One doc tagged with "expo-router" | Ignite Cookbook for React Native + + + + + + + + + \ No newline at end of file diff --git a/docs/tags/expo-updates/index.html b/docs/tags/expo-updates/index.html index 6613b903..54d935d2 100644 --- a/docs/tags/expo-updates/index.html +++ b/docs/tags/expo-updates/index.html @@ -8,8 +8,8 @@ One doc tagged with "expo-updates" | Ignite Cookbook for React Native - - + +
@@ -36,7 +36,7 @@

One doc tagged with "expo-updates"

View All Tags

EAS Update

Setting up Ignite to deploy over-the-air (OTA) updates via EAS

- - + + \ No newline at end of file diff --git a/docs/tags/expo/index.html b/docs/tags/expo/index.html index d9cdab4d..370fbaee 100644 --- a/docs/tags/expo/index.html +++ b/docs/tags/expo/index.html @@ -7,9 +7,9 @@ -5 docs tagged with "Expo" | Ignite Cookbook for React Native - - +6 docs tagged with "Expo" | Ignite Cookbook for React Native + +
@@ -35,8 +35,8 @@

Have an recipe idea for the cookbook? Contribute your ideas on GitHub!

-

5 docs tagged with "Expo"

View All Tags

EAS Update

Setting up Ignite to deploy over-the-air (OTA) updates via EAS

Staying With Expo

Setting up Ignite to build a custom Expo development client for use with Config Plugins

- - +

6 docs tagged with "Expo"

View All Tags

EAS Update

Setting up Ignite to deploy over-the-air (OTA) updates via EAS

Expo Router

How to convert Ignite v9 demo app to utilize `expo-router`

Staying With Expo

Setting up Ignite to build a custom Expo development client for use with Config Plugins

+ + \ No newline at end of file diff --git a/docs/tags/flat-list/index.html b/docs/tags/flat-list/index.html index 2aa9e88b..72138788 100644 --- a/docs/tags/flat-list/index.html +++ b/docs/tags/flat-list/index.html @@ -8,8 +8,8 @@ One doc tagged with "FlatList" | Ignite Cookbook for React Native - - + +
@@ -36,7 +36,7 @@

One doc tagged with "FlatList"

View All Tags
- - + + \ No newline at end of file diff --git a/docs/tags/generator/index.html b/docs/tags/generator/index.html index 2efd08e6..a806c99d 100644 --- a/docs/tags/generator/index.html +++ b/docs/tags/generator/index.html @@ -8,8 +8,8 @@ One doc tagged with "Generator" | Ignite Cookbook for React Native - - + +
@@ -36,7 +36,7 @@

One doc tagged with "Generator"

View All Tags
- - + + \ No newline at end of file diff --git a/docs/tags/guide/index.html b/docs/tags/guide/index.html index 6dd469db..5fb133e8 100644 --- a/docs/tags/guide/index.html +++ b/docs/tags/guide/index.html @@ -8,8 +8,8 @@ 6 docs tagged with "Guide" | Ignite Cookbook for React Native - - + +
@@ -36,7 +36,7 @@

6 docs tagged with "Guide"

View All Tags

Updating Dependencies with Yarn Audit, Outdated and Upgrade

If you get a bunch of warnings in the git command output about vulnerabilities, similar to this Github found 80 vulnerabilities on ..., you can examine these vulnerabilities with yarn audit, get a list of outdated packages with yarn outdated, and update each dependency using yarn update

- - + + \ No newline at end of file diff --git a/docs/tags/i-os/index.html b/docs/tags/i-os/index.html index 2c7a872c..3724cfc1 100644 --- a/docs/tags/i-os/index.html +++ b/docs/tags/i-os/index.html @@ -8,8 +8,8 @@ 2 docs tagged with "iOS" | Ignite Cookbook for React Native - - + +
@@ -36,7 +36,7 @@

2 docs tagged with "iOS"

View All Tags
- - + + \ No newline at end of file diff --git a/docs/tags/index.html b/docs/tags/index.html index 25dd1d3f..82e09077 100644 --- a/docs/tags/index.html +++ b/docs/tags/index.html @@ -8,8 +8,8 @@ Tags | Ignite Cookbook for React Native - - + +
@@ -35,8 +35,8 @@

Have an recipe idea for the cookbook? Contribute your ideas on GitHub!

- - - + + + \ No newline at end of file diff --git a/docs/tags/intro/index.html b/docs/tags/intro/index.html index d795a2b6..d441f768 100644 --- a/docs/tags/intro/index.html +++ b/docs/tags/intro/index.html @@ -8,8 +8,8 @@ 2 docs tagged with "Intro" | Ignite Cookbook for React Native - - + +
@@ -36,7 +36,7 @@

2 docs tagged with "Intro"

View All Tags

Detox Intro

A quick look at Detox and what makes it useful

Intro to Recipes

Welcome to the Ignite Cookbook! This is a collection of recipes for common patterns in Ignite projects.

- - + + \ No newline at end of file diff --git a/docs/tags/maestro/index.html b/docs/tags/maestro/index.html index c6826680..8fafc400 100644 --- a/docs/tags/maestro/index.html +++ b/docs/tags/maestro/index.html @@ -8,8 +8,8 @@ One doc tagged with "Maestro" | Ignite Cookbook for React Native - - + +
@@ -36,7 +36,7 @@

One doc tagged with "Maestro"

View All Tags
- - + + \ No newline at end of file diff --git a/docs/tags/mmkv/index.html b/docs/tags/mmkv/index.html index 59e4954b..492ec072 100644 --- a/docs/tags/mmkv/index.html +++ b/docs/tags/mmkv/index.html @@ -8,8 +8,8 @@ One doc tagged with "MMKV" | Ignite Cookbook for React Native - - + +
@@ -36,7 +36,7 @@

One doc tagged with "MMKV"

View All Tags
- - + + \ No newline at end of file diff --git a/docs/tags/mob-x/index.html b/docs/tags/mob-x/index.html index f65c3d9e..7e04dd14 100644 --- a/docs/tags/mob-x/index.html +++ b/docs/tags/mob-x/index.html @@ -8,8 +8,8 @@ One doc tagged with "MobX" | Ignite Cookbook for React Native - - + +
@@ -36,7 +36,7 @@

One doc tagged with "MobX"

View All Tags

Redux

How to migrate a Mobx-State-Tree project to Redux

- - + + \ No newline at end of file diff --git a/docs/tags/react-native-vision-camera/index.html b/docs/tags/react-native-vision-camera/index.html index 1b31a462..6b0bc180 100644 --- a/docs/tags/react-native-vision-camera/index.html +++ b/docs/tags/react-native-vision-camera/index.html @@ -8,8 +8,8 @@ One doc tagged with "react-native-vision-camera" | Ignite Cookbook for React Native - - + +
@@ -36,7 +36,7 @@

One doc tagged with "react-native-vision-camera"

View All Tags
- - + + \ No newline at end of file diff --git a/docs/tags/react-navigation/index.html b/docs/tags/react-navigation/index.html new file mode 100644 index 00000000..bdf9a05b --- /dev/null +++ b/docs/tags/react-navigation/index.html @@ -0,0 +1,42 @@ + + + + + + + + + +One doc tagged with "react-navigation" | Ignite Cookbook for React Native + + + + + + + + + \ No newline at end of file diff --git a/docs/tags/redux/index.html b/docs/tags/redux/index.html index ebfd1a95..ddfeca90 100644 --- a/docs/tags/redux/index.html +++ b/docs/tags/redux/index.html @@ -8,8 +8,8 @@ One doc tagged with "Redux" | Ignite Cookbook for React Native - - + +
@@ -36,7 +36,7 @@

One doc tagged with "Redux"

View All Tags

Redux

How to migrate a Mobx-State-Tree project to Redux

- - + + \ No newline at end of file diff --git a/docs/tags/scroll-to/index.html b/docs/tags/scroll-to/index.html index bf5193f9..833957b4 100644 --- a/docs/tags/scroll-to/index.html +++ b/docs/tags/scroll-to/index.html @@ -8,8 +8,8 @@ One doc tagged with "scrollTo" | Ignite Cookbook for React Native - - + +
@@ -36,7 +36,7 @@

One doc tagged with "scrollTo"

View All Tags
- - + + \ No newline at end of file diff --git a/docs/tags/section-list/index.html b/docs/tags/section-list/index.html index 48b7dcd3..0a012564 100644 --- a/docs/tags/section-list/index.html +++ b/docs/tags/section-list/index.html @@ -8,8 +8,8 @@ One doc tagged with "SectionList" | Ignite Cookbook for React Native - - + +
@@ -36,7 +36,7 @@

One doc tagged with "SectionList"

View All Tags
- - + + \ No newline at end of file diff --git a/docs/tags/select-field/index.html b/docs/tags/select-field/index.html index 4fc77894..4b29c195 100644 --- a/docs/tags/select-field/index.html +++ b/docs/tags/select-field/index.html @@ -8,8 +8,8 @@ One doc tagged with "SelectField" | Ignite Cookbook for React Native - - + +
@@ -36,7 +36,7 @@

One doc tagged with "SelectField"

View All Tags
- - + + \ No newline at end of file diff --git a/docs/tags/state-management/index.html b/docs/tags/state-management/index.html index a1cc2f2a..2608c4a3 100644 --- a/docs/tags/state-management/index.html +++ b/docs/tags/state-management/index.html @@ -8,8 +8,8 @@ One doc tagged with "State Management" | Ignite Cookbook for React Native - - + +
@@ -36,7 +36,7 @@

One doc tagged with "State Management"

View All Tags

Redux

How to migrate a Mobx-State-Tree project to Redux

- - + + \ No newline at end of file diff --git a/docs/tags/testing/index.html b/docs/tags/testing/index.html index a924fa0c..ab39a125 100644 --- a/docs/tags/testing/index.html +++ b/docs/tags/testing/index.html @@ -8,8 +8,8 @@ 2 docs tagged with "Testing" | Ignite Cookbook for React Native - - + +
@@ -36,7 +36,7 @@

2 docs tagged with "Testing"

View All Tags

Detox Intro

A quick look at Detox and what makes it useful

- - + + \ No newline at end of file diff --git a/docs/tags/text-field/index.html b/docs/tags/text-field/index.html index 9efca1bc..bcbe657c 100644 --- a/docs/tags/text-field/index.html +++ b/docs/tags/text-field/index.html @@ -8,8 +8,8 @@ One doc tagged with "TextField" | Ignite Cookbook for React Native - - + +
@@ -36,7 +36,7 @@

One doc tagged with "TextField"

View All Tags
- - + + \ No newline at end of file diff --git a/docs/tags/type-script/index.html b/docs/tags/type-script/index.html index 000072ae..23c2f850 100644 --- a/docs/tags/type-script/index.html +++ b/docs/tags/type-script/index.html @@ -8,8 +8,8 @@ One doc tagged with "TypeScript" | Ignite Cookbook for React Native - - + +
@@ -36,7 +36,7 @@

One doc tagged with "TypeScript"

View All Tags
- - + + \ No newline at end of file diff --git a/docs/tags/ui/index.html b/docs/tags/ui/index.html index 7b35daa7..932d303a 100644 --- a/docs/tags/ui/index.html +++ b/docs/tags/ui/index.html @@ -8,8 +8,8 @@ 2 docs tagged with "UI" | Ignite Cookbook for React Native - - + +
@@ -36,7 +36,7 @@

2 docs tagged with "UI"

View All Tags
- - + + \ No newline at end of file diff --git a/docs/tags/vision-camera/index.html b/docs/tags/vision-camera/index.html index 873dd5be..3eb98acd 100644 --- a/docs/tags/vision-camera/index.html +++ b/docs/tags/vision-camera/index.html @@ -8,8 +8,8 @@ One doc tagged with "VisionCamera" | Ignite Cookbook for React Native - - + +
@@ -36,7 +36,7 @@

One doc tagged with "VisionCamera"

View All Tags
- - + + \ No newline at end of file diff --git a/docs/tags/yarn/index.html b/docs/tags/yarn/index.html index 43eea0fb..1f024591 100644 --- a/docs/tags/yarn/index.html +++ b/docs/tags/yarn/index.html @@ -8,8 +8,8 @@ One doc tagged with "Yarn" | Ignite Cookbook for React Native - - + +
@@ -36,7 +36,7 @@

One doc tagged with "Yarn"

View All Tags

Updating Dependencies with Yarn Audit, Outdated and Upgrade

If you get a bunch of warnings in the git command output about vulnerabilities, similar to this Github found 80 vulnerabilities on ..., you can examine these vulnerabilities with yarn audit, get a list of outdated packages with yarn outdated, and update each dependency using yarn update

- - + + \ No newline at end of file diff --git a/index.html b/index.html index cb494d62..b922249f 100644 --- a/index.html +++ b/index.html @@ -8,8 +8,8 @@ Ignite Cookbook for React Native | Ignite Cookbook for React Native - - + +
@@ -35,8 +35,8 @@

Have an recipe idea for the cookbook? Contribute your ideas on GitHub!

-

New Recipe

Redux

Published on January 16th, 2024 by Justin Poliachik

View recipe

Releases

Ignite Exp[ress]o ☕️

v9.0.5 released 67 days ago

View on Github

Proven Recipes for your React Native apps

Starting from scratch doesn’t always make sense. That’s why we made the Ignite Cookbook for React Native – an easy way for developers to browse and share code snippets (or “recipes”) that actually work.

Spin Up Your App In Record Time

Stop reinventing the wheel on every project. Use the Ignite CLI to get your app started. Then, hop over to the Ignite Cookbook for React Native to browse for things like libraries in “cookie cutter” templates that work for almost any project. It’s the fastest way to get a React Native app off the ground.

Animation ImageAnimation ImageAnimation ImageAnimation ImageAnimation ImageAnimation Image

Find Quality Code When You Need It

The popular forum sites are great for finding code until you realize it’s based on an old version of React Native. Ignite Cookbook is a place for recipes that work as of the time they’re published – meaning, it worked when it was posted. And if it ever goes out of date, we’ll make sure the community knows on what version it was last working.

updated ...
Animation Image

Backed By A Community of React Native Experts

The Ignite Cookbook isn’t just a random group of code snippets. It’s a curated collection of usable code samples that the Infinite Red team’s used in their own React Native projects. Having worked with some of the biggest clients in the tech industry, we know a thing or two about keeping our code to a high standard. You can code confidently!

Animation ImageAnimation ImageAnimation ImageAnimation ImageAnimation ImageAnimation ImageAnimation ImageAnimation ImageAnimation ImageAnimation ImageAnimation Image
- - +

New Recipe

"Go Back",

Published on January 25th, 2024 by Frank Calise & Justin Poliachik

View recipe

Releases

Ignite Exp[ress]o ☕️

v9.0.5 released 69 days ago

View on Github

Proven Recipes for your React Native apps

Starting from scratch doesn’t always make sense. That’s why we made the Ignite Cookbook for React Native – an easy way for developers to browse and share code snippets (or “recipes”) that actually work.

Spin Up Your App In Record Time

Stop reinventing the wheel on every project. Use the Ignite CLI to get your app started. Then, hop over to the Ignite Cookbook for React Native to browse for things like libraries in “cookie cutter” templates that work for almost any project. It’s the fastest way to get a React Native app off the ground.

Animation ImageAnimation ImageAnimation ImageAnimation ImageAnimation ImageAnimation Image

Find Quality Code When You Need It

The popular forum sites are great for finding code until you realize it’s based on an old version of React Native. Ignite Cookbook is a place for recipes that work as of the time they’re published – meaning, it worked when it was posted. And if it ever goes out of date, we’ll make sure the community knows on what version it was last working.

updated ...
Animation Image

Backed By A Community of React Native Experts

The Ignite Cookbook isn’t just a random group of code snippets. It’s a curated collection of usable code samples that the Infinite Red team’s used in their own React Native projects. Having worked with some of the biggest clients in the tech industry, we know a thing or two about keeping our code to a high standard. You can code confidently!

Animation ImageAnimation ImageAnimation ImageAnimation ImageAnimation ImageAnimation ImageAnimation ImageAnimation ImageAnimation ImageAnimation ImageAnimation Image
+ + \ No newline at end of file diff --git a/search-index-docs-default-current.json b/search-index-docs-default-current.json index ad6fdb2a..4aa864ae 100644 --- a/search-index-docs-default-current.json +++ b/search-index-docs-default-current.json @@ -1 +1 @@ -{"documents":[{"id":1,"pageTitle":"","sectionTitle":"Welcome to the Ignite Cookbook 👋","sectionRoute":"/docs/intro","type":"docs"},{"id":2,"pageTitle":"","sectionTitle":"What is a Recipe?","sectionRoute":"/docs/intro#what-is-a-recipe","type":"docs"},{"id":3,"pageTitle":"","sectionTitle":"Who is this for?","sectionRoute":"/docs/intro#who-is-this-for","type":"docs"},{"id":4,"pageTitle":"","sectionTitle":"Are these recipes tested and up-to-date?","sectionRoute":"/docs/intro#are-these-recipes-tested-and-up-to-date","type":"docs"},{"id":5,"pageTitle":"","sectionTitle":"Backed by the Ignite Team & Community","sectionRoute":"/docs/intro#backed-by-the-ignite-team--community","type":"docs"},{"id":6,"pageTitle":"","sectionTitle":"Have an idea for a recipe?","sectionRoute":"/docs/intro#have-an-idea-for-a-recipe","type":"docs"},{"id":7,"pageTitle":"","sectionTitle":"Is this page still up to date? Did it work for you?","sectionRoute":"/docs/intro","type":"docs"},{"id":12,"pageTitle":"","sectionTitle":"Dealing With Accessibility Font Sizes in React Native","sectionRoute":"/docs/recipes/AccessibilityFontSizes","type":"docs"},{"id":13,"pageTitle":"","sectionTitle":"Is this page still up to date? Did it work for you?","sectionRoute":"/docs/recipes/AccessibilityFontSizes","type":"docs"},{"id":26,"pageTitle":"CircleCI CD Setup - React Native","sectionTitle":"CircleCI CD Setup - React Native","sectionRoute":"/docs/recipes/CircleCIRNSetup","type":"docs"},{"id":27,"pageTitle":"CircleCI CD Setup - React Native","sectionTitle":"First Things First","sectionRoute":"/docs/recipes/CircleCIRNSetup#first-things-first","type":"docs"},{"id":28,"pageTitle":"CircleCI CD Setup - React Native","sectionTitle":"CircleCI Setup","sectionRoute":"/docs/recipes/CircleCIRNSetup#circleci-setup","type":"docs"},{"id":29,"pageTitle":"CircleCI CD Setup - React Native","sectionTitle":"Continuous Integration","sectionRoute":"/docs/recipes/CircleCIRNSetup#continuous-integration","type":"docs"},{"id":30,"pageTitle":"CircleCI CD Setup - React Native","sectionTitle":"iOS Continuous Deployment","sectionRoute":"/docs/recipes/CircleCIRNSetup#ios-continuous-deployment","type":"docs"},{"id":31,"pageTitle":"CircleCI CD Setup - React Native","sectionTitle":"Is this page still up to date? Did it work for you?","sectionRoute":"/docs/recipes/CircleCIRNSetup","type":"docs"},{"id":14,"pageTitle":"Creating a Good Experience for Screen Readers","sectionTitle":"Creating a Good Experience for Screen Readers","sectionRoute":"/docs/recipes/CreatingGreateExperienceForScreenReaders","type":"docs"},{"id":15,"pageTitle":"Creating a Good Experience for Screen Readers","sectionTitle":"UI Patterns","sectionRoute":"/docs/recipes/CreatingGreateExperienceForScreenReaders#ui-patterns","type":"docs"},{"id":16,"pageTitle":"Creating a Good Experience for Screen Readers","sectionTitle":"Screens","sectionRoute":"/docs/recipes/CreatingGreateExperienceForScreenReaders#screens","type":"docs"},{"id":17,"pageTitle":"Creating a Good Experience for Screen Readers","sectionTitle":"Common patterns that require more work to add good UX for screen readers","sectionRoute":"/docs/recipes/CreatingGreateExperienceForScreenReaders#common-patterns-that-require-more-work-to-add-good-ux-for-screen-readers","type":"docs"},{"id":18,"pageTitle":"Creating a Good Experience for Screen Readers","sectionTitle":"RN-specific issues","sectionRoute":"/docs/recipes/CreatingGreateExperienceForScreenReaders#rn-specific-issues","type":"docs"},{"id":19,"pageTitle":"Creating a Good Experience for Screen Readers","sectionTitle":"Labeling","sectionRoute":"/docs/recipes/CreatingGreateExperienceForScreenReaders#labeling","type":"docs"},{"id":20,"pageTitle":"Creating a Good Experience for Screen Readers","sectionTitle":"Is this page still up to date? Did it work for you?","sectionRoute":"/docs/recipes/CreatingGreateExperienceForScreenReaders","type":"docs"},{"id":8,"pageTitle":"Detox Intro","sectionTitle":"Detox Intro","sectionRoute":"/docs/recipes/DetoxIntro","type":"docs"},{"id":9,"pageTitle":"Detox Intro","sectionTitle":"Installation","sectionRoute":"/docs/recipes/DetoxIntro#installation","type":"docs"},{"id":10,"pageTitle":"Detox Intro","sectionTitle":"What's unique about Detox","sectionRoute":"/docs/recipes/DetoxIntro#whats-unique-about-detox","type":"docs"},{"id":11,"pageTitle":"Detox Intro","sectionTitle":"Is this page still up to date? Did it work for you?","sectionRoute":"/docs/recipes/DetoxIntro","type":"docs"},{"id":21,"pageTitle":"","sectionTitle":"Distributing Auth Token to APISauce","sectionRoute":"/docs/recipes/DistributingAuthTokenToAPI","type":"docs"},{"id":22,"pageTitle":"","sectionTitle":"Review of API Instance and Auth Store","sectionRoute":"/docs/recipes/DistributingAuthTokenToAPI#review-of-api-instance-and-auth-store","type":"docs"},{"id":23,"pageTitle":"","sectionTitle":"Distributing Auth Token to API Instance","sectionRoute":"/docs/recipes/DistributingAuthTokenToAPI#distributing-auth-token-to-api-instance","type":"docs"},{"id":24,"pageTitle":"","sectionTitle":"Other configuration","sectionRoute":"/docs/recipes/DistributingAuthTokenToAPI#other-configuration","type":"docs"},{"id":25,"pageTitle":"","sectionTitle":"Is this page still up to date? Did it work for you?","sectionRoute":"/docs/recipes/DistributingAuthTokenToAPI","type":"docs"},{"id":43,"pageTitle":"","sectionTitle":"EAS Update","sectionRoute":"/docs/recipes/EASUpdate","type":"docs"},{"id":44,"pageTitle":"","sectionTitle":"Appetizer","sectionRoute":"/docs/recipes/EASUpdate#appetizer","type":"docs"},{"id":45,"pageTitle":"","sectionTitle":"Steps","sectionRoute":"/docs/recipes/EASUpdate#steps","type":"docs"},{"id":46,"pageTitle":"","sectionTitle":"1. Project Setup","sectionRoute":"/docs/recipes/EASUpdate#1-project-setup","type":"docs"},{"id":47,"pageTitle":"","sectionTitle":"2. Edit Build Profiles","sectionRoute":"/docs/recipes/EASUpdate#2-edit-build-profiles","type":"docs"},{"id":48,"pageTitle":"","sectionTitle":"3. Create the Build","sectionRoute":"/docs/recipes/EASUpdate#3-create-the-build","type":"docs"},{"id":49,"pageTitle":"","sectionTitle":"4. Making a Project Update","sectionRoute":"/docs/recipes/EASUpdate#4-making-a-project-update","type":"docs"},{"id":50,"pageTitle":"","sectionTitle":"5. Publishing OTA","sectionRoute":"/docs/recipes/EASUpdate#5-publishing-ota","type":"docs"},{"id":51,"pageTitle":"","sectionTitle":"Customized Update Flow","sectionRoute":"/docs/recipes/EASUpdate#customized-update-flow","type":"docs"},{"id":52,"pageTitle":"","sectionTitle":"Notes","sectionRoute":"/docs/recipes/EASUpdate#notes","type":"docs"},{"id":53,"pageTitle":"","sectionTitle":"More Resources","sectionRoute":"/docs/recipes/EASUpdate#more-resources","type":"docs"},{"id":54,"pageTitle":"","sectionTitle":"Is this page still up to date? Did it work for you?","sectionRoute":"/docs/recipes/EASUpdate","type":"docs"},{"id":68,"pageTitle":"","sectionTitle":"Environment Variables","sectionRoute":"/docs/recipes/EnvironmentVariables","type":"docs"},{"id":69,"pageTitle":"","sectionTitle":"Setup","sectionRoute":"/docs/recipes/EnvironmentVariables#setup","type":"docs"},{"id":70,"pageTitle":"","sectionTitle":"Install","sectionRoute":"/docs/recipes/EnvironmentVariables#install","type":"docs"},{"id":71,"pageTitle":"","sectionTitle":"Configure","sectionRoute":"/docs/recipes/EnvironmentVariables#configure","type":"docs"},{"id":72,"pageTitle":"","sectionTitle":"Usage","sectionRoute":"/docs/recipes/EnvironmentVariables#usage","type":"docs"},{"id":73,"pageTitle":"","sectionTitle":"Is this page still up to date? Did it work for you?","sectionRoute":"/docs/recipes/EnvironmentVariables","type":"docs"},{"id":32,"pageTitle":"","sectionTitle":"Add component tests to npx ignite-cli generate component","sectionRoute":"/docs/recipes/GeneratorComponentTests","type":"docs"},{"id":33,"pageTitle":"","sectionTitle":"Setup @testing-library/react-native","sectionRoute":"/docs/recipes/GeneratorComponentTests#setup-testing-libraryreact-native","type":"docs"},{"id":34,"pageTitle":"","sectionTitle":"Component Generators","sectionRoute":"/docs/recipes/GeneratorComponentTests#component-generators","type":"docs"},{"id":35,"pageTitle":"","sectionTitle":"Customizing Component Generators","sectionRoute":"/docs/recipes/GeneratorComponentTests#customizing-component-generators","type":"docs"},{"id":36,"pageTitle":"","sectionTitle":"Testing","sectionRoute":"/docs/recipes/GeneratorComponentTests#testing","type":"docs"},{"id":37,"pageTitle":"","sectionTitle":"Is this page still up to date? Did it work for you?","sectionRoute":"/docs/recipes/GeneratorComponentTests","type":"docs"},{"id":123,"pageTitle":"","sectionTitle":"Setting Up Maestro in Ignite","sectionRoute":"/docs/recipes/MaestroSetup","type":"docs"},{"id":124,"pageTitle":"","sectionTitle":"Overview","sectionRoute":"/docs/recipes/MaestroSetup#overview","type":"docs"},{"id":125,"pageTitle":"","sectionTitle":"Maestro Installation","sectionRoute":"/docs/recipes/MaestroSetup#maestro-installation","type":"docs"},{"id":126,"pageTitle":"","sectionTitle":"Creating our first Maestro Flow","sectionRoute":"/docs/recipes/MaestroSetup#creating-our-first-maestro-flow","type":"docs"},{"id":127,"pageTitle":"","sectionTitle":"Let's see what else Maestro can do","sectionRoute":"/docs/recipes/MaestroSetup#lets-see-what-else-maestro-can-do","type":"docs"},{"id":128,"pageTitle":"","sectionTitle":"Conclusion","sectionRoute":"/docs/recipes/MaestroSetup#conclusion","type":"docs"},{"id":129,"pageTitle":"","sectionTitle":"Notes","sectionRoute":"/docs/recipes/MaestroSetup#notes","type":"docs"},{"id":130,"pageTitle":"","sectionTitle":"Is this page still up to date? Did it work for you?","sectionRoute":"/docs/recipes/MaestroSetup","type":"docs"},{"id":38,"pageTitle":"","sectionTitle":"Migrating to MMKV","sectionRoute":"/docs/recipes/MigratingToMMKV","type":"docs"},{"id":39,"pageTitle":"","sectionTitle":"Overview","sectionRoute":"/docs/recipes/MigratingToMMKV#overview","type":"docs"},{"id":40,"pageTitle":"","sectionTitle":"Project Dependencies","sectionRoute":"/docs/recipes/MigratingToMMKV#project-dependencies","type":"docs"},{"id":41,"pageTitle":"","sectionTitle":"Code Changes","sectionRoute":"/docs/recipes/MigratingToMMKV#code-changes","type":"docs"},{"id":42,"pageTitle":"","sectionTitle":"Is this page still up to date? Did it work for you?","sectionRoute":"/docs/recipes/MigratingToMMKV","type":"docs"},{"id":55,"pageTitle":"Patching/Building Android .aar From Source","sectionTitle":"Patching/Building Android .aar From Source","sectionRoute":"/docs/recipes/PatchingBuildingAndroid","type":"docs"},{"id":56,"pageTitle":"Patching/Building Android .aar From Source","sectionTitle":"Why?","sectionRoute":"/docs/recipes/PatchingBuildingAndroid#why","type":"docs"},{"id":57,"pageTitle":"Patching/Building Android .aar From Source","sectionTitle":"Official Guides","sectionRoute":"/docs/recipes/PatchingBuildingAndroid#official-guides","type":"docs"},{"id":58,"pageTitle":"Patching/Building Android .aar From Source","sectionTitle":"Steps","sectionRoute":"/docs/recipes/PatchingBuildingAndroid#steps","type":"docs"},{"id":59,"pageTitle":"Patching/Building Android .aar From Source","sectionTitle":"Is this page still up to date? Did it work for you?","sectionRoute":"/docs/recipes/PatchingBuildingAndroid","type":"docs"},{"id":60,"pageTitle":"","sectionTitle":"Pristine Expo Project","sectionRoute":"/docs/recipes/PristineExpoProject","type":"docs"},{"id":61,"pageTitle":"","sectionTitle":"Notes","sectionRoute":"/docs/recipes/PristineExpoProject#notes","type":"docs"},{"id":62,"pageTitle":"","sectionTitle":"Steps","sectionRoute":"/docs/recipes/PristineExpoProject#steps","type":"docs"},{"id":63,"pageTitle":"","sectionTitle":"Project Initialization","sectionRoute":"/docs/recipes/PristineExpoProject#project-initialization","type":"docs"},{"id":64,"pageTitle":"","sectionTitle":"Filesystem Changes","sectionRoute":"/docs/recipes/PristineExpoProject#filesystem-changes","type":"docs"},{"id":65,"pageTitle":"","sectionTitle":"Package Changes","sectionRoute":"/docs/recipes/PristineExpoProject#package-changes","type":"docs"},{"id":66,"pageTitle":"","sectionTitle":"package.json Script Updates","sectionRoute":"/docs/recipes/PristineExpoProject#packagejson-script-updates","type":"docs"},{"id":67,"pageTitle":"","sectionTitle":"Is this page still up to date? Did it work for you?","sectionRoute":"/docs/recipes/PristineExpoProject","type":"docs"},{"id":91,"pageTitle":"","sectionTitle":"VisionCamera","sectionRoute":"/docs/recipes/ReactNativeVisionCamera","type":"docs"},{"id":92,"pageTitle":"","sectionTitle":"Overview","sectionRoute":"/docs/recipes/ReactNativeVisionCamera#overview","type":"docs"},{"id":93,"pageTitle":"","sectionTitle":"Installation","sectionRoute":"/docs/recipes/ReactNativeVisionCamera#installation","type":"docs"},{"id":94,"pageTitle":"","sectionTitle":"Permissions","sectionRoute":"/docs/recipes/ReactNativeVisionCamera#permissions","type":"docs"},{"id":95,"pageTitle":"","sectionTitle":"Codes Store & Screen","sectionRoute":"/docs/recipes/ReactNativeVisionCamera#codes-store--screen","type":"docs"},{"id":96,"pageTitle":"","sectionTitle":"Displaying the Camera","sectionRoute":"/docs/recipes/ReactNativeVisionCamera#displaying-the-camera","type":"docs"},{"id":97,"pageTitle":"","sectionTitle":"Is this page still up to date? Did it work for you?","sectionRoute":"/docs/recipes/ReactNativeVisionCamera","type":"docs"},{"id":77,"pageTitle":"","sectionTitle":"Redux","sectionRoute":"/docs/recipes/Redux","type":"docs"},{"id":78,"pageTitle":"","sectionTitle":"Remove Mobx-State-Tree","sectionRoute":"/docs/recipes/Redux#remove-mobx-state-tree","type":"docs"},{"id":79,"pageTitle":"","sectionTitle":"Add Redux","sectionRoute":"/docs/recipes/Redux#add-redux","type":"docs"},{"id":80,"pageTitle":"","sectionTitle":"Persistence","sectionRoute":"/docs/recipes/Redux#persistence","type":"docs"},{"id":81,"pageTitle":"","sectionTitle":"Reactotron Support","sectionRoute":"/docs/recipes/Redux#reactotron-support","type":"docs"},{"id":82,"pageTitle":"","sectionTitle":"Is this page still up to date? Did it work for you?","sectionRoute":"/docs/recipes/Redux","type":"docs"},{"id":74,"pageTitle":"Sample YAML for CircleCi for Ignite","sectionTitle":"Sample YAML for CircleCi for Ignite","sectionRoute":"/docs/recipes/SampleYAMLCircleCI","type":"docs"},{"id":75,"pageTitle":"Sample YAML for CircleCi for Ignite","sectionTitle":"Sampl YAML File","sectionRoute":"/docs/recipes/SampleYAMLCircleCI#sampl-yaml-file","type":"docs"},{"id":76,"pageTitle":"Sample YAML for CircleCi for Ignite","sectionTitle":"Is this page still up to date? Did it work for you?","sectionRoute":"/docs/recipes/SampleYAMLCircleCI","type":"docs"},{"id":131,"pageTitle":"","sectionTitle":"SelectField using react-native-bottom-sheet","sectionRoute":"/docs/recipes/SelectFieldWithBottomSheet","type":"docs"},{"id":132,"pageTitle":"","sectionTitle":"1. Installation","sectionRoute":"/docs/recipes/SelectFieldWithBottomSheet#1-installation","type":"docs"},{"id":133,"pageTitle":"","sectionTitle":"2. Create the SelectField.tsx Component File","sectionRoute":"/docs/recipes/SelectFieldWithBottomSheet#2-create-the-selectfieldtsx-component-file","type":"docs"},{"id":134,"pageTitle":"","sectionTitle":"3. Add New Props and Customize the TextField","sectionRoute":"/docs/recipes/SelectFieldWithBottomSheet#3-add-new-props-and-customize-the-textfield","type":"docs"},{"id":135,"pageTitle":"","sectionTitle":"Add a Caret Icon Accessory","sectionRoute":"/docs/recipes/SelectFieldWithBottomSheet#add-a-caret-icon-accessory","type":"docs"},{"id":136,"pageTitle":"","sectionTitle":"Add Props","sectionRoute":"/docs/recipes/SelectFieldWithBottomSheet#add-props","type":"docs"},{"id":137,"pageTitle":"","sectionTitle":"Add Logic to Display Selected Options","sectionRoute":"/docs/recipes/SelectFieldWithBottomSheet#add-logic-to-display-selected-options","type":"docs"},{"id":138,"pageTitle":"","sectionTitle":"Full Code For This Step","sectionRoute":"/docs/recipes/SelectFieldWithBottomSheet#full-code-for-this-step","type":"docs"},{"id":139,"pageTitle":"","sectionTitle":"4. Add the Sheet Components","sectionRoute":"/docs/recipes/SelectFieldWithBottomSheet#4-add-the-sheet-components","type":"docs"},{"id":140,"pageTitle":"","sectionTitle":"Add the BottomSheetModalProvider","sectionRoute":"/docs/recipes/SelectFieldWithBottomSheet#add-the-bottomsheetmodalprovider","type":"docs"},{"id":141,"pageTitle":"","sectionTitle":"Add the Necessary Components to SelectField","sectionRoute":"/docs/recipes/SelectFieldWithBottomSheet#add-the-necessary-components-to-selectfield","type":"docs"},{"id":142,"pageTitle":"","sectionTitle":"5. Add Selected State to Options and Hook Up Callback","sectionRoute":"/docs/recipes/SelectFieldWithBottomSheet#5-add-selected-state-to-options-and-hook-up-callback","type":"docs"},{"id":143,"pageTitle":"","sectionTitle":"Is this page still up to date? Did it work for you?","sectionRoute":"/docs/recipes/SelectFieldWithBottomSheet","type":"docs"},{"id":83,"pageTitle":"","sectionTitle":"Staying With Expo","sectionRoute":"/docs/recipes/StayingWithExpo","type":"docs"},{"id":84,"pageTitle":"","sectionTitle":"Appetizer","sectionRoute":"/docs/recipes/StayingWithExpo#appetizer","type":"docs"},{"id":85,"pageTitle":"","sectionTitle":"Steps","sectionRoute":"/docs/recipes/StayingWithExpo#steps","type":"docs"},{"id":86,"pageTitle":"","sectionTitle":"1. Project Setup","sectionRoute":"/docs/recipes/StayingWithExpo#1-project-setup","type":"docs"},{"id":87,"pageTitle":"","sectionTitle":"2. Build Profile","sectionRoute":"/docs/recipes/StayingWithExpo#2-build-profile","type":"docs"},{"id":88,"pageTitle":"","sectionTitle":"3. Run the Build!","sectionRoute":"/docs/recipes/StayingWithExpo#3-run-the-build","type":"docs"},{"id":89,"pageTitle":"","sectionTitle":"4. Run the Development Client","sectionRoute":"/docs/recipes/StayingWithExpo#4-run-the-development-client","type":"docs"},{"id":90,"pageTitle":"","sectionTitle":"Is this page still up to date? Did it work for you?","sectionRoute":"/docs/recipes/StayingWithExpo","type":"docs"},{"id":98,"pageTitle":"","sectionTitle":"Switch a Project Between Expo Go and Expo CNG","sectionRoute":"/docs/recipes/SwitchBetweenExpoGoCNG","type":"docs"},{"id":99,"pageTitle":"","sectionTitle":"Expo Go -> Expo CNG","sectionRoute":"/docs/recipes/SwitchBetweenExpoGoCNG#expo-go---expo-cng","type":"docs"},{"id":100,"pageTitle":"","sectionTitle":"Expo CNG -> Expo Go","sectionRoute":"/docs/recipes/SwitchBetweenExpoGoCNG#expo-cng---expo-go","type":"docs"},{"id":101,"pageTitle":"","sectionTitle":"Steps","sectionRoute":"/docs/recipes/SwitchBetweenExpoGoCNG#steps","type":"docs"},{"id":102,"pageTitle":"","sectionTitle":"Is this page still up to date? Did it work for you?","sectionRoute":"/docs/recipes/SwitchBetweenExpoGoCNG","type":"docs"},{"id":115,"pageTitle":"","sectionTitle":"TypeScript baseUrl Configuration","sectionRoute":"/docs/recipes/TypeScriptBaseURL","type":"docs"},{"id":116,"pageTitle":"","sectionTitle":"Overview","sectionRoute":"/docs/recipes/TypeScriptBaseURL#overview","type":"docs"},{"id":117,"pageTitle":"","sectionTitle":"Project Dependencies","sectionRoute":"/docs/recipes/TypeScriptBaseURL#project-dependencies","type":"docs"},{"id":118,"pageTitle":"","sectionTitle":"TypeScript Configuration Changes","sectionRoute":"/docs/recipes/TypeScriptBaseURL#typescript-configuration-changes","type":"docs"},{"id":119,"pageTitle":"","sectionTitle":"Babel Configuration Changes","sectionRoute":"/docs/recipes/TypeScriptBaseURL#babel-configuration-changes","type":"docs"},{"id":120,"pageTitle":"","sectionTitle":"Taste Test in a Component!","sectionRoute":"/docs/recipes/TypeScriptBaseURL#taste-test-in-a-component","type":"docs"},{"id":121,"pageTitle":"","sectionTitle":"Resources","sectionRoute":"/docs/recipes/TypeScriptBaseURL#resources","type":"docs"},{"id":122,"pageTitle":"","sectionTitle":"Is this page still up to date? Did it work for you?","sectionRoute":"/docs/recipes/TypeScriptBaseURL","type":"docs"},{"id":103,"pageTitle":"Scrolling to a location that hasn't been rendered using FlatList or SectionList","sectionTitle":"Scrolling to a location that hasn't been rendered using FlatList or SectionList","sectionRoute":"/docs/recipes/UnrenderedItemInScrollView","type":"docs"},{"id":104,"pageTitle":"Scrolling to a location that hasn't been rendered using FlatList or SectionList","sectionTitle":"Is this page still up to date? Did it work for you?","sectionRoute":"/docs/recipes/UnrenderedItemInScrollView","type":"docs"},{"id":105,"pageTitle":"Updating Dependencies with Yarn Audit, Outdated and Upgrade","sectionTitle":"Updating Dependencies with Yarn Audit, Outdated and Upgrade","sectionRoute":"/docs/recipes/UpdatingDependencies","type":"docs"},{"id":106,"pageTitle":"Updating Dependencies with Yarn Audit, Outdated and Upgrade","sectionTitle":"Is this page still up to date? Did it work for you?","sectionRoute":"/docs/recipes/UpdatingDependencies","type":"docs"},{"id":107,"pageTitle":"","sectionTitle":"Using Screen Readers","sectionRoute":"/docs/recipes/UsingScreenReaders","type":"docs"},{"id":108,"pageTitle":"","sectionTitle":"iOS","sectionRoute":"/docs/recipes/UsingScreenReaders#ios","type":"docs"},{"id":109,"pageTitle":"","sectionTitle":"On a simulator","sectionRoute":"/docs/recipes/UsingScreenReaders#on-a-simulator","type":"docs"},{"id":110,"pageTitle":"","sectionTitle":"On a device","sectionRoute":"/docs/recipes/UsingScreenReaders#on-a-device","type":"docs"},{"id":111,"pageTitle":"","sectionTitle":"Android","sectionRoute":"/docs/recipes/UsingScreenReaders#android","type":"docs"},{"id":112,"pageTitle":"","sectionTitle":"Devices with TalkBack installed","sectionRoute":"/docs/recipes/UsingScreenReaders#devices-with-talkback-installed","type":"docs"},{"id":113,"pageTitle":"","sectionTitle":"Devices with Voice Assistant and not TalkBack","sectionRoute":"/docs/recipes/UsingScreenReaders#devices-with-voice-assistant-and-not-talkback","type":"docs"},{"id":114,"pageTitle":"","sectionTitle":"Is this page still up to date? Did it work for you?","sectionRoute":"/docs/recipes/UsingScreenReaders","type":"docs"}],"index":{"version":"2.3.9","fields":["title","content","tags"],"fieldVectors":[["title/1",[0,3.332,1,1.115,2,3.332,3,0.871]],["content/1",[1,2.111,4,5.596,5,1.933,6,4.784,7,4.079,8,1.292,9,5.131,10,4.784,11,5.131,12,4.507,13,3.489,14,6.301,15,6.301,16,4.079,17,5.131,18,2.502,19,3.374,20,3.906,21,3.906,22,3.077,23,2.991,24,4.079]],["tags/1",[25,1.903]],["title/2",[5,1.939]],["content/2",[1,1.69,4,5.507,5,2.352,6,4.709,7,4.015,8,1.572,26,2.352,27,2.3,28,5.507,29,6.201,30,1.69,31,5.05,32,4.709,33,4.436,34,6.201,35,2.943,36,4.436,37,2.109,38,5.507,39,4.436,40,4.015,41,2.201,42,5.05]],["tags/2",[]],["title/3",[]],["content/3",[1,2.36,7,3.616,8,1.626,13,3.093,16,3.616,27,2.071,35,2.651,37,1.899,43,5.585,44,2.991,45,4.548,46,2.121,47,1.821,48,2.604,49,3.462,50,2.511,51,2.071,52,5.585,53,4.96,54,3.975,55,2.919,56,4.548,57,3.616,58,2.167,59,4.96,60,3.462]],["tags/3",[]],["title/4",[5,1.255,61,1.391,62,0.777,63,1.552]],["content/4",[1,1.69,5,2.554,12,4.436,31,5.05,40,4.015,62,1.178,63,2.908,64,5.485,65,4.015,66,4.209,67,3.434,68,5.05,69,2.501,70,4.436,71,3.119,72,4.015,73,3.434,74,5.507,75,3.694,76,6.201]],["tags/4",[]],["title/5",[1,0.998,3,0.779,12,2.619,24,2.37,65,2.37]],["content/5",[1,1.851,2,5.53,10,5.156,11,5.53,12,4.858,65,4.396,70,4.858,77,5.53,78,6.79,79,2.9,80,6.79,81,4.858,82,6.79,83,6.79]],["tags/5",[]],["title/6",[5,1.641,84,4.356]],["content/6",[2,5.483,18,2.674,55,2.738,64,4.816,70,4.816,71,3.386,72,4.358,84,5.483,85,6.732,86,6.732,87,5.483,88,4.358,89,5.483,90,3.605,91,1.636]],["tags/6",[]],["title/7",[58,1.421,62,0.696,63,1.389,69,1.194,92,1.194]],["content/7",[5,2.324,25,5.419]],["tags/7",[]],["title/12",[46,0.886,47,0.76,93,2.942,94,1.572,95,2.515,96,2.515]],["content/12",[3,2.039,8,0.267,24,0.845,36,0.933,45,1.062,46,1.461,47,0.299,48,0.473,60,0.809,67,0.722,73,0.722,75,0.777,79,1.833,94,1.474,95,4.894,96,3.259,97,1.305,98,1.305,99,1.159,100,0.571,101,2.686,102,0.484,103,0.518,104,1.305,105,1.236,106,1.495,107,3.755,108,1.159,109,1.159,110,1.305,111,1.305,112,0.885,113,1.305,114,1.159,115,1.753,116,1.375,117,2.087,118,1.611,119,1.305,120,1.305,121,1.305,122,1.305,123,1.305,124,1.652,125,3.812,126,1.305,127,1.305,128,1.305,129,1.305,130,1.305,131,1.305,132,3.027,133,1.305,134,1.305,135,1.159,136,1.305,137,4.292,138,1.127,139,1.753,140,1.159,141,1.159,142,1.159,143,2.759,144,2.222,145,1.305,146,1.305,147,1.305,148,3.496,149,3.106,150,1.305,151,3.106,152,1.305,153,3.674,154,7.204,155,2.159,156,1.159,157,1.8,158,1.062,159,1.305,160,2.309,161,1.305,162,1.305,163,2.317,164,2.309,165,2.851,166,1.782,167,3.058,168,7.613,169,4.745,170,4.745,171,1.305,172,1.562,173,1.305,174,1.305,175,1.159,176,2.011,177,1.305,178,2.309,179,1.305,180,3.106,181,1.305,182,2.309,183,2.309,184,1.305,185,2.309,186,1.305,187,2.309,188,1.305,189,1.159,190,2.309,191,1.062,192,1.305,193,1.062,194,1.062,195,1.305,196,3.106,197,1.305,198,1.305,199,1.305,200,0.991,201,1.305,202,1.305,203,1.305,204,1.305,205,1.305,206,1.305,207,1.305,208,1.159,209,1.159,210,0.531,211,1.062,212,0.991,213,1.305,214,1.305,215,1.305,216,1.305,217,1.159,218,0.885,219,0.991,220,1.305,221,1.305,222,0.991,223,1.062,224,1.305,225,1.062,226,1.88,227,1.305,228,1.159,229,0.933,230,1.305,231,1.305,232,1.305,233,1.305,234,2.851,235,0.933,236,1.305,237,1.305,238,1.305,239,0.933]],["tags/12",[94,1.263]],["title/13",[58,1.421,62,0.696,63,1.389,69,1.194,92,1.194]],["content/13",[5,2.28,95,5.643,96,5.643,240,7.432]],["tags/13",[]],["title/26",[46,0.979,47,0.84,241,2.1,242,2.37,243,1.691]],["content/26",[26,2.449,37,2.195,38,5.733,61,2.195,62,1.227,138,2.342,241,3.704,244,3.575,245,4.382,246,4.18,247,6.98,248,4.003,249,5.258,250,5.258,251,5.733,252,4.18,253,6.456,254,4.382,255,4.382]],["tags/26",[256,0.686,257,1.427]],["title/27",[112,3.147,258,3.513]],["content/27",[10,4.984,11,5.345,30,1.789,46,1.755,47,1.507,48,2.381,61,2.902,62,1.247,138,2.381,259,5.679,260,4.069,261,5.345,262,3.635,263,3.205,264,6.564]],["tags/27",[]],["title/28",[241,3.069,243,2.47]],["content/28",[3,1.23,22,1.982,26,1.539,30,2.197,35,1.926,37,2.741,62,1.098,71,3.386,79,1.733,91,0.986,102,1.505,106,2.627,124,2.903,138,3.009,176,2.173,241,2.328,254,3.923,255,3.923,258,2.247,265,3.304,266,4.389,267,2.903,268,4.569,269,4.058,270,4.058,271,4.389,272,3.304,273,3.081,274,2.417,275,4.707,276,2.754,277,3.603,278,4.058,279,3.603,280,2.903,281,3.304,282,4.058,283,3.304,284,1.777,285,1.65,286,3.304,287,3.304,288,2.903,289,3.304,290,3.081,291,2.627,292,3.603,293,1.612,294,2.754,295,2.516,296,4.707,297,5.133,298,2.192,299,5.78,300,4.389,301,4.358,302,1.982,303,3.081]],["tags/28",[]],["title/29",[248,3.316,249,4.356]],["content/29",[3,1.911,8,1.15,13,1.651,19,2.462,22,1.456,26,2.128,30,0.813,41,1.632,49,1.848,51,1.105,57,1.93,61,2.317,79,1.273,100,1.306,102,1.105,116,2.738,210,2.928,241,1.71,242,1.93,243,2.591,260,1.848,262,1.651,268,2.023,273,2.263,281,3.744,289,2.428,304,3.744,305,1.71,306,3.909,307,1.915,308,2.023,309,2.132,310,2.428,311,1.826,312,2.245,313,2.835,314,2.647,315,2.91,316,5.697,317,2.647,318,2.647,319,2.428,320,2.637,321,3.744,322,3.491,323,3.744,324,3.219,325,5.549,326,4.57,327,3.773,328,3.491,329,3.289,330,3.289,331,3.491,332,3.491,333,3.491,334,2.288,335,1.744,336,3.492,337,1.784,338,2.428,339,2.023,340,2.132,341,2.132,342,2.263,343,4.083,344,2.647,345,3.219,346,1.93,347,2.428,348,2.023,349,1.596]],["tags/29",[]],["title/30",[248,2.875,350,1.932,351,3.776]],["content/30",[3,1.822,8,0.362,13,0.978,17,0.789,22,1.915,23,0.46,26,0.924,27,0.655,30,1.171,36,0.693,37,1.573,39,0.693,40,0.627,41,0.627,46,0.472,47,0.406,48,1.268,49,0.601,51,1.454,55,1.222,57,1.144,60,1.095,61,0.601,62,0.184,65,1.144,66,0.657,67,0.536,72,0.627,79,0.414,91,1.37,94,1.156,99,0.86,100,0.424,101,2.5,102,1.593,105,0.519,106,0.627,115,0.736,118,0.502,138,1.881,142,0.86,166,0.46,167,0.789,191,0.789,210,1.421,219,0.736,235,0.693,241,3.111,243,2.136,246,0.627,248,0.601,250,4.417,251,2.669,254,2.04,259,0.693,262,0.978,263,1.468,265,1.984,266,1.342,267,0.693,273,2.977,275,1.439,279,0.86,281,2.447,283,1.439,285,0.394,286,1.439,287,0.789,289,2.846,290,0.736,294,1.199,298,0.924,302,0.473,306,3.451,307,1.015,309,1.264,311,0.702,312,0.473,313,0.436,315,2.033,316,2.654,319,2.447,320,1.398,321,2.447,322,1.85,323,1.439,324,2.654,325,2.846,326,2.447,327,1.349,328,0.736,329,1.743,330,0.693,331,0.736,332,1.85,333,0.736,334,2.348,335,1.487,336,3.507,337,0.686,338,1.439,339,0.657,340,1.743,341,1.743,342,0.736,345,1.724,346,0.627,347,0.789,348,1.199,349,1.304,350,1.634,351,1.984,352,0.657,353,1.264,354,1.569,355,1.439,356,0.693,357,0.789,358,0.969,359,0.969,360,0.969,361,1.767,362,1.743,363,2.436,364,1.984,365,0.969,366,0.969,367,2.436,368,0.969,369,0.969,370,0.969,371,0.969,372,0.969,373,0.969,374,0.969,375,0.969,376,0.969,377,0.969,378,0.969,379,0.969,380,0.889,381,0.86,382,0.969,383,0.969,384,0.946,385,0.969,386,0.969,387,0.736,388,0.969,389,0.969,390,1.569,391,0.789,392,0.969,393,0.789,394,0.736,395,2.163,396,0.86,397,0.969,398,0.359,399,1.569,400,1.569,401,1.577,402,2.661,403,1.767,404,2.163,405,0.969,406,0.969,407,0.969,408,0.969,409,0.789,410,1.439,411,1.767,412,0.577,413,1.125,414,0.627,415,0.969,416,0.86,417,2.5,418,0.969,419,0.969,420,0.86,421,1.125,422,1.342,423,0.969,424,1.767,425,2.654,426,0.86,427,0.969,428,1.569,429,0.969,430,0.601,431,0.969,432,1.569,433,0.969,434,1.767,435,3.495,436,0.969,437,0.86,438,0.969,439,0.789,440,1.767,441,0.86,442,1.767,443,0.736,444,1.569,445,0.789,446,0.577,447,3.005,448,1.439,449,0.86,450,0.969,451,0.556,452,0.736,453,0.86,454,0.969,455,0.789,456,0.969,457,0.969,458,0.86,459,0.86,460,0.969,461,1.767,462,0.969,463,4.295,464,2.436,465,0.969,466,0.736,467,0.969,468,0.969,469,0.969,470,0.86,471,0.86,472,1.767,473,0.969,474,0.969,475,0.789,476,0.969,477,0.969,478,0.969,479,0.969,480,0.969,481,0.969,482,0.86,483,0.969,484,0.969,485,1.439,486,0.969,487,0.693,488,0.969,489,0.969,490,0.969,491,5.034,492,0.969,493,0.969,494,0.969,495,1.767,496,1.743,497,0.969,498,0.969,499,1.569,500,0.969,501,2.669,502,0.86,503,0.86,504,0.86,505,0.969,506,0.969,507,0.969,508,0.86,509,0.969,510,0.86,511,0.969,512,1.767,513,3.104,514,1.767,515,1.569,516,0.969,517,1.767,518,0.969,519,3.005,520,1.569,521,0.969,522,0.969,523,0.969,524,0.789,525,0.86,526,0.789,527,1.767,528,0.969,529,0.969,530,0.969,531,0.577,532,0.969,533,0.969,534,0.969,535,0.627,536,0.969,537,0.86,538,0.969,539,0.969,540,1.767,541,0.969,542,0.969,543,0.969]],["tags/30",[]],["title/31",[58,1.421,62,0.696,63,1.389,69,1.194,92,1.194]],["content/31",[5,2.238,46,1.95,47,1.675,241,4.185,242,4.722,243,3.368]],["tags/31",[]],["title/14",[41,1.299,398,1.358,544,2.27,545,2.981,546,2.181]],["content/14",[]],["tags/14",[94,0.546,103,0.457,350,0.48]],["title/15",[7,3.463,547,3.631]],["content/15",[]],["tags/15",[]],["title/16",[398,2.344]],["content/16",[6,3.163,8,1.207,33,2.979,46,1.114,47,0.956,48,1.511,54,2.306,62,0.791,94,1.977,102,2.184,106,2.696,108,3.699,109,3.699,112,2.827,135,3.699,263,2.875,301,4.421,398,2.753,452,3.163,546,2.481,548,5.229,549,5.888,550,3.163,551,6.065,552,3.163,553,2.979,554,5.186,555,5.888,556,4.165,557,3.392,558,2.696,559,2.979,560,4.165,561,2.827,562,6.83,563,5.636,564,4.165,565,4.165,566,3.699,567,4.795,568,3.699,569,4.165,570,4.165,571,4.165,572,4.421,573,4.795,574,4.165,575,4.165,576,3.699,577,2.23,578,4.165,579,3.699,580,1.977,581,2.827,582,3.699,583,3.163,584,2.23,585,4.165,586,2.827,587,4.165,588,2.582,589,3.392,590,3.392]],["tags/16",[]],["title/17",[6,1.822,7,1.553,69,0.782,91,0.583,348,1.628,398,0.89,421,1.108,544,1.487,546,1.429,591,2.131]],["content/17",[8,1.161,10,5.5,42,4.614,51,2.101,60,4.491,172,2.849,210,2.304,298,2.149,320,3.25,352,3.845,398,2.101,470,5.031,520,6.433,546,3.374,572,4.69,592,4.69,593,5.031,594,4.614,595,4.302,596,5.031,597,3.668,598,4.614,599,7.244,600,5.665,601,5.665,602,5.665,603,5.665,604,5.665,605,4.614,606,5.665,607,3.137]],["tags/17",[]],["title/18",[72,3.002,608,4.118,609,3.776]],["content/18",[45,4.392,51,2,61,1.834,71,2.713,91,1.311,94,2.56,100,2.363,115,4.095,118,2.797,132,4.743,157,2.046,350,2.247,354,4.79,355,4.392,398,2,546,3.212,558,3.492,572,3.492,580,3.331,588,4.351,593,4.79,605,4.392,610,7.018,611,4.392,612,5.393,613,5.393,614,3.661,615,4.392,616,5.393,617,7.018,618,5.393,619,3.858,620,4.095,621,4.392,622,4.79,623,4.79]],["tags/18",[]],["title/19",[624,4.092]],["content/19",[8,1.407,94,3.258,102,2.546,105,3.676,139,3.959,176,3.676,261,4.247,262,2.888,272,4.247,349,2.792,355,4.247,398,2.546,430,3.233,531,3.106,544,3.233,546,3.106,550,3.959,559,3.73,563,3.959,572,3.376,586,3.539,588,4.757,598,4.247,624,5.279,625,5.215,626,6.096,627,4.631,628,3.959,629,4.247,630,5.215,631,4.631,632,5.215,633,5.215,634,3.959,635,4.247,636,5.215,637,5.215]],["tags/19",[]],["title/20",[58,1.421,62,0.696,63,1.389,69,1.194,92,1.194]],["content/20",[5,2.238,41,2.589,398,2.705,544,4.522,545,5.94,546,4.345]],["tags/20",[]],["title/8",[25,3.827,638,3.316]],["content/8",[8,1.392,46,1.815,47,1.559,48,2.463,60,5.023,61,2.309,577,3.636,607,3.76,638,5.023,639,6.79,640,6.031,641,6.79]],["tags/8",[25,1.149,61,0.546]],["title/9",[335,2.397]],["content/9",[1,1.97,73,4.002,244,4.002,313,3.249,335,2.741,362,5.17,642,6.418]],["tags/9",[]],["title/10",[550,3.521,638,2.875,643,4.637]],["content/10",[23,2.099,26,1.677,41,1.57,46,1.182,47,1.015,48,2.227,55,1.799,61,2.723,65,2.863,67,2.449,72,2.863,102,1.64,244,2.449,248,2.742,256,1.889,259,3.164,262,3.4,263,2.16,291,2.863,295,2.742,312,2.16,324,2.537,349,2.368,362,3.164,417,3.164,421,2.042,422,3.358,525,3.928,526,3.602,550,3.358,552,3.358,638,5.138,642,3.928,644,5.454,645,3.602,646,3.288,647,3.928,648,2.742,649,3.928,650,4.423,651,4.423,652,3.602,653,4.423,654,4.423,655,4.423,656,4.423,657,4.423,658,4.423,659,4.423,660,4.423,661,3.928,662,4.423,663,4.423,664,4.423,665,4.423,666,4.423,667,4.423,668,3.928,669,4.423,670,4.423,671,3.928,672,4.423,673,3.602]],["tags/10",[]],["title/11",[58,1.421,62,0.696,63,1.389,69,1.194,92,1.194]],["content/11",[5,2.302,25,5.367,638,4.652]],["tags/11",[]],["title/21",[414,2.649,674,2.777,675,2.927,676,2.777]],["content/21",[1,1.789,5,2.014,16,4.249,37,2.232,102,2.434,245,4.455,255,4.455,380,3.301,409,5.345,646,3.515,676,4.455,677,3.635,678,4.069,679,5.679,680,4.249,681,4.069,682,6.564]],["tags/21",[256,0.492,676,0.781,679,0.823]],["title/22",[64,2.619,380,1.841,414,2.37,680,2.37,681,2.27]],["content/22",[3,2.008,8,0.618,16,1.952,35,1.431,41,1.07,44,2.483,51,1.118,55,1.226,60,1.869,64,2.157,88,1.952,117,1.226,138,1.094,148,2.541,155,1.517,163,3.679,166,1.431,263,2.265,292,2.678,293,1.198,294,3.148,295,1.869,298,1.144,307,1.932,311,1.198,380,2.333,414,3.002,446,1.796,553,2.157,559,2.157,584,2.483,646,1.615,652,2.455,675,2.157,676,3.148,677,1.67,678,1.869,679,2.157,680,4.434,681,4.821,683,1.472,684,3.015,685,5.652,686,5.652,687,2.678,688,4.638,689,5.652,690,3.015,691,3.015,692,3.777,693,3.015,694,3.015,695,3.015,696,3.015,697,3.015,698,2.047,699,3.015,700,3.015,701,2.678,702,3.015,703,2.289,704,3.015,705,2.678,706,2.678,707,3.015,708,3.015,709,2.678,710,3.015,711,1.73,712,3.015,713,2.678,714,3.002,715,5.652,716,3.015,717,2.678,718,3.015,719,2.678,720,3.015,721,2.678,722,2.678,723,1.796,724,2.678,725,2.678,726,2.678,727,3.015,728,2.678]],["tags/22",[]],["title/23",[414,2.37,674,2.485,675,2.619,680,2.37,681,2.27]],["content/23",[3,1.963,8,0.56,17,2.225,18,1.085,27,1.013,50,1.931,51,1.593,55,1.111,56,2.225,68,2.225,91,1.044,100,1.882,102,1.013,105,1.463,117,1.747,138,1.558,148,2.386,153,1.334,166,2.52,172,1.374,255,3.603,263,1.334,291,1.769,293,2.39,311,1.085,348,1.855,349,1.463,362,3.073,380,1.374,414,3.437,446,4.137,487,3.797,559,3.073,583,2.075,586,1.855,631,2.427,674,2.916,675,5.537,676,1.855,679,4.68,681,3.731,711,3.984,717,2.427,719,2.427,721,2.427,722,2.427,723,2.559,724,3.815,725,3.815,729,1.855,730,6.945,731,2.427,732,2.427,733,3.815,734,2.732,735,2.732,736,2.427,737,2.732,738,1.955,739,2.732,740,2.732,741,1.955,742,2.732,743,2.732,744,2.427,745,2.427,746,1.627,747,6.542,748,1.955,749,4.296,750,2.732,751,2.732,752,2.732,753,2.427,754,3.498,755,1.769,756,4.296,757,4.296,758,2.732,759,2.732,760,1.955,761,2.732,762,2.732,763,2.732,764,2.732,765,2.732,766,2.732,767,2.732,768,2.732,769,2.732,770,1.228,771,2.732,772,2.427]],["tags/23",[]],["title/24",[311,2.511]],["content/24",[19,3.636,69,2.215,293,2.697,294,4.609,313,3.053,580,3.223,635,5.53,676,4.609,680,4.396,681,5.023,746,4.044,773,6.152]],["tags/24",[]],["title/25",[58,1.421,62,0.696,63,1.389,69,1.194,92,1.194]],["content/25",[5,2.259,414,4.767,674,4.997,675,5.267,681,4.565]],["tags/25",[]],["title/43",[293,2.125,774,2.864]],["content/43",[1,1.851,20,4.21,30,1.851,62,1.29,138,2.463,256,2.9,293,3.218,774,3.636,775,5.53,776,6.031,777,5.156,778,2.042,779,4.396]],["tags/43",[778,0.346,780,1.151,781,1.151]],["title/44",[782,5.614]],["content/44",[5,1.859,13,3.355,22,2.958,27,2.247,30,2.06,35,2.875,51,2.247,54,3.355,102,2.247,258,3.355,260,3.756,267,4.334,302,2.958,335,2.866,349,3.244,774,4.047,778,2.477,783,4.6,784,3.69,785,5.38,786,4.112,787,4.6]],["tags/44",[]],["title/45",[26,2.397]],["content/45",[]],["tags/45",[]],["title/46",[30,1.264,172,2.332,243,2.141]],["content/46",[8,1.048,18,2.031,19,2.738,27,1.896,30,2.071,55,2.079,62,0.971,91,1.242,102,1.896,103,2.031,138,1.855,256,2.184,285,2.079,293,2.691,307,2.823,311,3.018,324,2.933,334,1.855,335,1.939,413,2.361,421,2.361,583,3.882,746,3.045,770,2.299,774,4.333,778,2.037,779,3.31,788,2.933,789,2.652,790,4.541,791,5.113,792,3.657,793,4.164,794,5.113,795,5.113,796,4.164,797,4.387,798,4.541,799,3.657,800,3.882,801,5.113]],["tags/46",[]],["title/47",[37,1.391,320,2.347,796,3.332,802,2.347]],["content/47",[3,2.018,8,1.315,18,1.872,37,2.662,48,1.71,61,1.603,75,2.808,92,1.537,103,2.897,112,3.2,311,1.872,315,2.445,350,1.964,384,2.524,513,4.187,674,3.2,784,2.302,800,3.58,802,2.704,803,2.923,804,3.839,805,2.119,806,4.522,807,6.416,808,5.225,809,3.58,810,5.94,811,4.714,812,2.611,813,4.187,814,3.839,815,4.187,816,2.808,817,2.808,818,4.187]],["tags/47",[]],["title/48",[37,1.577,41,1.646,819,3.147]],["content/48",[3,1.558,8,0.972,18,1.884,19,2.54,21,4.536,37,2.488,41,1.683,55,1.929,61,1.613,62,0.901,91,1.152,103,3.117,105,2.54,116,2.825,144,3.393,226,3.862,267,3.393,295,2.94,701,4.212,729,3.219,760,3.393,774,4.533,793,3.862,802,3.696,805,2.132,806,3.994,820,5.722,821,3.696,822,3.45,823,5.082,824,5.247,825,4.743,826,5.722,827,4.743,828,4.212,829,4.743,830,4.212,831,4.212,832,4.743,833,4.212]],["tags/48",[]],["title/49",[30,1.115,102,1.517,293,1.625,834,2.777]],["content/49",[1,1.367,3,1.424,62,0.953,70,3.587,71,2.522,102,2.481,132,4.446,211,4.084,235,3.587,263,2.449,284,2.197,285,2.72,293,1.992,298,2.537,303,3.808,334,1.819,351,4.084,353,4.785,554,5.079,559,4.785,683,3.267,753,4.454,770,2.255,777,3.808,835,3.808,836,5.015,837,5.015,838,2.777,839,4.454,840,4.454,841,4.084,842,6.689,843,5.015,844,6.689,845,6.689,846,5.015,847,3.587,848,3.404,849,3.808,850,4.454,851,5.015]],["tags/49",[]],["title/50",[229,3.317,777,3.521,852,3.776]],["content/50",[0,2.716,18,1.325,20,3.104,21,2.068,23,1.583,26,1.265,36,2.386,37,1.134,41,1.184,48,2.829,54,1.847,55,2.036,62,0.634,64,2.386,67,3.329,68,2.716,70,2.386,90,1.786,92,1.088,124,2.386,138,1.21,193,2.716,252,2.159,285,2.445,293,3.454,295,2.068,306,1.913,313,1.499,332,2.532,353,3.582,356,2.386,380,1.677,390,2.962,391,2.716,398,1.857,413,1.54,420,2.962,466,2.532,487,2.386,496,2.386,535,2.159,554,2.532,583,2.532,619,2.386,729,2.264,760,2.386,770,3.004,774,3.835,776,2.962,777,2.532,778,1.506,800,2.532,802,1.913,806,3.727,815,6.679,822,2.681,834,2.264,841,2.716,852,4.077,853,3.335,854,3.335,855,2.716,856,3.335,857,3.335,858,2.716,859,2.068,860,3.335,861,4.447,862,3.335,863,3.335,864,2.532,865,2.962,866,4.447,867,5.007,868,3.335,869,2.159,870,3.335,871,3.335,872,2.386,873,2.716,874,3.335,875,3.335,876,3.335,877,2.962,878,2.962,879,2.962,880,2.716,881,3.335]],["tags/50",[]],["title/51",[293,1.842,580,2.201,869,3.002]],["content/51",[3,1.825,12,4.06,20,2.452,21,2.452,23,3.15,26,1.5,27,1.467,37,1.345,48,2.059,49,2.452,50,1.778,75,2.356,90,2.118,91,0.961,101,5.188,102,1.467,105,2.118,116,2.356,144,2.83,229,2.83,252,2.561,255,2.685,256,1.689,263,1.932,268,2.685,285,1.609,293,3.27,302,2.772,312,1.932,349,3.039,391,3.221,413,1.826,417,2.83,421,2.621,535,2.561,545,3.221,547,2.685,563,3.003,577,2.118,580,1.877,614,2.685,635,3.221,648,2.452,649,3.513,652,4.622,778,1.189,797,2.561,841,3.221,858,3.221,869,3.674,882,3.956,883,3.956,884,3.956,885,3.956,886,3.513,887,3.956,888,3.956,889,3.221,890,3.513,891,3.513,892,3.956,893,3.513,894,3.513,895,5.04,896,3.956,897,3.956,898,2.685,899,3.956,900,3.956,901,3.956]],["tags/51",[]],["title/52",[413,2.919]],["content/52",[22,3.153,47,1.482,49,4.003,74,5.733,102,2.394,244,3.575,284,2.828,285,3.196,295,4.003,309,4.618,315,3.348,430,4.003,778,1.941,797,4.18,902,4.618,903,5.258,904,6.456,905,6.456,906,4.618]],["tags/52",[]],["title/53",[421,2.47,590,4.356]],["content/53",[8,1.38,37,2.741,57,4.358,293,3.427,334,2.442,607,3.728,774,4.62,778,2.024,907,6.732,908,6.732]],["tags/53",[]],["title/54",[58,1.421,62,0.696,63,1.389,69,1.194,92,1.194]],["content/54",[5,2.302,293,2.98,774,4.018]],["tags/54",[]],["title/68",[401,3.463,402,3.631]],["content/68",[]],["tags/68",[256,0.686,909,1.607]],["title/69",[243,2.919]],["content/69",[]],["tags/69",[]],["title/70",[335,2.397]],["content/70",[91,1.74,337,2.779,455,6.808,910,6.36,911,4.861,912,4.265,913,6.36]],["tags/70",[]],["title/71",[311,2.511]],["content/71",[3,1.999,46,1.766,47,1.516,48,1.785,69,1.605,91,1.196,100,2.156,148,2.969,263,2.403,311,1.954,384,2.635,413,3.05,425,3.736,455,5.379,778,1.48,810,4.007,911,3.34,912,4.44,913,5.866,914,5.866,915,4.921,916,6.605,917,6.605,918,4.921,919,4.921,920,4.37,921,4.37,922,4.921,923,3.52,924,4.921,925,6.605,926,4.007]],["tags/71",[]],["title/72",[158,5.148]],["content/72",[3,1.571,30,1.59,33,4.173,41,2.07,94,2.769,102,2.163,166,2.769,285,2.372,302,3.604,305,3.346,307,3.075,330,4.173,401,3.777,402,3.959,416,6.554,425,5.603,597,3.777,760,4.173,770,2.623,849,4.429,894,5.181,927,5.833,928,5.833,929,5.603,930,5.833,931,5.833,932,5.833]],["tags/72",[]],["title/73",[58,1.421,62,0.696,63,1.389,69,1.194,92,1.194]],["content/73",[5,2.302,401,4.857,402,5.093]],["tags/73",[]],["title/32",[1,0.759,61,0.946,91,0.676,157,1.653,784,1.359,789,1.443,805,1.251]],["content/32",[1,1.804,8,1.357,47,1.52,61,2.713,157,2.51,247,7.086,307,2.758,312,3.232,552,5.026,580,3.142,620,5.026,805,3.851,933,5.026]],["tags/32",[805,1.196]],["title/33",[47,0.939,61,1.391,243,1.889,933,3.107]],["content/33",[1,1.819,27,2.475,30,1.819,47,1.532,53,5.928,61,2.27,79,2.851,91,1.622,243,3.082,256,2.851,258,3.696,933,5.069,934,6.675,935,6.675,936,6.675,937,6.675]],["tags/33",[]],["title/34",[157,2.029,805,2.405]],["content/34",[1,2.3,8,1.055,41,2.415,57,3.332,90,2.756,157,2.892,258,2.85,259,3.681,298,1.952,306,2.952,307,2.144,310,6.209,313,2.314,334,1.867,336,2.85,394,3.908,421,2.376,430,3.191,577,2.756,741,3.681,748,3.681,784,3.323,788,2.952,789,3.529,802,2.952,805,3.647,938,5.146,939,5.146,940,4.57,941,5.146,942,5.542,943,5.146,944,5.146,945,4.57,946,4.191,947,4.57]],["tags/34",[]],["title/35",[157,1.759,580,2.201,805,2.085]],["content/35",[1,1.325,3,2.029,27,1.802,41,1.725,46,1.751,47,1.116,61,1.653,91,1.181,117,3.013,157,1.843,307,2.025,334,1.763,398,1.802,746,2.895,770,2.185,784,2.373,789,2.52,802,2.788,805,2.185,933,3.69,942,3.958,947,4.316,948,6.55,949,4.86,950,4.86,951,4.86,952,4.86,953,4.973,954,7.041,955,4.316,956,4.86,957,4.86,958,4.86]],["tags/35",[]],["title/36",[61,2.149]],["content/36",[51,2.54,55,2.786,61,2.769,62,1.301,138,2.485,334,2.485,337,2.658,673,5.578,741,4.9,770,3.079,959,5.578,960,5.578]],["tags/36",[]],["title/37",[58,1.421,62,0.696,63,1.389,69,1.194,92,1.194]],["content/37",[5,2.28,61,2.527,157,2.819,805,3.341]],["tags/37",[]],["title/123",[1,1.115,62,0.777,138,1.484,961,2.191]],["content/123",[]],["tags/123",[61,0.546,961,0.86]],["title/124",[962,4.8]],["content/124",[1,1.651,5,1.859,30,1.651,60,4.685,61,2.57,62,1.565,77,6.154,138,2.988,705,5.38,809,4.6,848,4.112,878,5.38,886,5.38,961,4.047,963,6.154,964,5.38,965,4.334,966,6.058,967,4.334]],["tags/124",[]],["title/125",[335,2.029,961,2.864]],["content/125",[3,1.088,18,2.031,23,2.427,27,1.896,35,2.427,41,1.815,51,2.513,67,2.831,72,3.31,88,3.31,116,3.045,256,2.184,258,2.831,260,3.17,298,1.939,302,3.309,334,2.458,335,3.193,336,2.831,421,2.361,504,4.541,508,4.541,640,4.541,729,3.47,784,2.497,822,2.738,869,3.31,961,4.069,965,3.657,968,3.882,969,5.113,970,5.113,971,4.164,972,5.113,973,6.776,974,6.776,975,6.776,976,3.47,977,5.113,978,4.164]],["tags/125",[]],["title/126",[41,1.452,258,2.266,869,2.649,961,2.191]],["content/126",[1,0.974,3,1.847,8,1.08,19,1.914,22,1.061,23,1.032,27,1.325,30,1.24,35,2.502,37,0.739,41,1.615,48,2.849,51,0.806,54,1.204,61,1.792,62,0.679,66,1.475,67,1.204,71,1.797,79,1.944,88,2.946,90,1.164,91,0.528,102,0.806,103,0.863,132,2.919,141,1.93,157,1.355,176,1.914,242,1.407,252,1.407,258,2.919,262,2.52,291,2.313,298,1.999,302,1.061,304,2.91,305,1.247,307,1.896,313,1.607,334,1.912,336,1.204,337,0.843,350,1.896,353,3.771,396,3.174,398,1.325,399,3.174,443,2.713,446,2.128,487,3.255,572,1.407,586,1.475,597,2.946,598,2.91,614,1.475,646,2.437,679,1.555,683,2.844,711,3.024,729,1.475,741,2.556,778,1.075,788,1.247,797,1.407,812,1.204,816,1.295,822,1.164,838,1.204,849,1.65,855,1.77,859,1.348,869,4.773,898,1.475,906,1.555,961,3.544,967,1.555,968,1.65,976,4.251,978,2.91,979,2.174,980,4.041,981,2.174,982,4.041,983,4.041,984,1.77,985,2.174,986,3.574,987,3.574,988,4.423,989,4.681,990,4.041,991,5.825,992,1.555,993,1.77,994,2.174,995,2.713,996,4.293,997,1.407,998,1.348,999,1.77,1000,2.174,1001,2.174,1002,1.77,1003,1.77,1004,2.174,1005,2.174,1006,2.174,1007,2.174,1008,2.174,1009,2.174]],["tags/126",[]],["title/127",[262,2.568,683,2.264,961,2.483]],["content/127",[1,0.601,3,0.469,8,1.09,18,0.875,19,2.846,24,1.427,27,1.34,28,1.957,30,0.601,40,1.427,41,1.283,46,0.966,47,0.83,51,0.817,54,1.22,55,1.47,61,0.749,62,0.687,66,2.453,79,1.962,88,3.441,89,1.795,90,2.46,91,0.878,94,2.523,106,2.975,112,1.496,125,1.957,132,3.986,138,1.311,157,0.836,176,1.936,209,3.21,212,4.456,219,1.673,234,2.745,245,3.119,258,1.22,291,1.427,298,0.836,300,3.489,312,1.076,320,1.264,334,2.287,350,0.918,352,1.496,356,1.577,398,1.704,401,2.34,402,2.453,404,1.957,412,3.166,421,1.018,425,3.489,443,1.673,446,1.313,487,2.586,548,5.211,568,1.957,572,3.799,586,1.496,592,1.427,614,1.496,624,3.441,634,1.673,661,1.957,668,1.957,683,1.765,692,2.944,706,4.081,711,3.82,741,1.577,779,1.427,798,1.957,816,1.313,819,1.496,834,1.496,838,2.002,839,1.957,869,4.913,961,1.18,964,1.957,980,3.21,982,1.957,983,1.957,989,4.081,990,4.721,992,1.577,996,1.795,997,2.975,1010,2.204,1011,2.204,1012,1.427,1013,6.174,1014,6.578,1015,2.204,1016,2.204,1017,2.204,1018,1.957,1019,2.204,1020,5.868,1021,3.615,1022,1.795,1023,2.204,1024,4.595,1025,1.577,1026,3.615,1027,3.615,1028,3.615,1029,3.615,1030,3.615,1031,1.673,1032,1.673,1033,4.081,1034,2.745,1035,2.204,1036,2.204,1037,2.204,1038,2.204,1039,2.204,1040,2.204,1041,2.204,1042,2.204]],["tags/127",[]],["title/128",[1043,6.321]],["content/128",[1,1.939,3,1.172,8,1.458,23,3.376,30,1.939,61,2.419,62,1.046,67,3.939,73,3.939,77,4.484,79,2.352,91,1.338,138,1.997,244,3.049,261,4.484,268,3.738,313,2.476,413,2.543,451,3.159,638,4.41,645,4.484,809,5.401,961,4.459,963,5.792,965,5.088,1044,5.507,1045,4.484]],["tags/128",[]],["title/129",[413,2.919]],["content/129",[1,1.883,8,1.416,30,1.883,61,2.35,268,4.69,313,3.107,451,3.964,638,5.075,961,3.7,963,5.627,965,4.943]],["tags/129",[]],["title/130",[58,1.421,62,0.696,63,1.389,69,1.194,92,1.194]],["content/130",[5,2.302,243,3.465,961,4.018]],["tags/130",[]],["title/38",[1046,4.356,1047,3.631]],["content/38",[]],["tags/38",[1047,1.09,1048,1.22]],["title/39",[962,4.8]],["content/39",[1,2.002,5,1.776,8,1.506,18,2.3,30,1.578,46,1.548,47,1.329,55,2.355,242,3.749,284,2.537,576,5.142,644,5.142,784,2.828,789,3.003,792,4.142,823,3.749,838,3.206,848,3.93,929,4.397,1047,4.986,1048,4.397,1049,5.79,1050,5.79,1051,6.126,1052,5.79,1053,3.749,1054,5.142,1055,5.982]],["tags/39",[]],["title/40",[30,1.458,210,2.176]],["content/40",[1,1.717,30,2.111,46,2.07,47,1.778,62,1.197,91,1.531,138,2.286,210,2.563,312,3.077,334,2.286,335,2.937,337,2.445,345,3.615,413,2.909,510,5.596,992,4.507,1047,5.256,1056,6.301]],["tags/40",[]],["title/41",[284,2.343,285,2.176]],["content/41",[1,0.491,3,2.013,18,0.715,20,1.116,22,0.879,39,1.288,46,1.063,47,0.913,48,1.442,50,3.268,55,0.732,57,1.166,61,0.612,62,0.342,69,0.587,71,1.536,117,1.242,139,1.367,148,1.787,153,3.25,163,3.55,166,3.27,176,2.129,239,4.075,245,1.222,262,0.997,271,1.367,285,0.732,290,1.367,291,1.166,298,0.683,311,0.715,324,4.068,334,1.108,337,0.699,339,2.072,350,1.272,353,1.288,380,1.536,384,1.635,398,0.668,412,1.072,430,1.116,451,1.752,502,4.159,561,3.866,597,1.977,608,1.599,622,1.599,681,1.116,683,1.491,703,4.61,723,4.582,748,1.288,770,1.787,803,1.116,816,1.072,817,1.819,864,1.367,865,1.599,866,1.599,898,2.072,920,5.058,923,1.288,976,2.072,1002,2.486,1013,2.712,1034,2.318,1047,3.558,1048,3.019,1051,4.61,1057,1.8,1058,1.466,1059,1.8,1060,1.466,1061,5.392,1062,3.053,1063,1.8,1064,4.639,1065,3.053,1066,3.053,1067,1.8,1068,1.8,1069,3.975,1070,3.053,1071,2.184,1072,3.053,1073,1.8,1074,1.8,1075,1.8,1076,3.053,1077,1.8,1078,3.053,1079,1.8,1080,1.466,1081,3.053,1082,3.053,1083,1.599,1084,3.053,1085,3.053,1086,2.072,1087,1.8,1088,1.8,1089,1.8,1090,1.8,1091,1.8,1092,1.8,1093,1.8,1094,1.599]],["tags/41",[]],["title/42",[58,1.421,62,0.696,63,1.389,69,1.194,92,1.194]],["content/42",[5,2.302,1046,6.11,1047,5.093]],["tags/42",[]],["title/55",[103,1.625,301,2.649,1095,3.634,1096,3.332]],["content/55",[]],["tags/55",[103,0.457,256,0.492,526,0.937]],["title/56",[]],["content/56",[8,1.326,9,3.886,37,1.623,46,1.962,47,1.685,48,2.347,51,1.77,55,2.631,79,2.038,103,2.915,114,4.238,263,2.33,284,2.09,293,1.895,301,4.188,307,1.988,315,3.806,496,3.413,586,3.239,595,3.623,596,4.238,614,3.239,621,3.886,824,3.886,831,4.238,848,3.239,879,5.745,880,5.268,889,3.886,902,4.628,997,3.089,1032,3.623,1096,3.886,1097,6.469,1098,4.772,1099,3.886,1100,4.772,1101,4.238,1102,4.772,1103,4.772,1104,5.268,1105,4.772,1106,4.772,1107,3.886,1108,4.772,1109,4.772]],["tags/56",[]],["title/57",[256,2.285,1110,4.356]],["content/57",[26,2.88,37,2.076,46,2.03,47,1.743,66,4.144,69,1.991,243,2.819,256,2.607,260,3.785,301,3.952,309,4.367,312,2.981,401,3.952,577,3.269,619,4.367,805,2.745,812,3.381,955,5.422,997,3.952,1110,4.972,1111,6.105,1112,6.105,1113,6.105,1114,6.105]],["tags/57",[]],["title/58",[26,2.397]],["content/58",[8,0.472,13,1.274,18,0.914,21,2.321,22,1.124,23,1.092,26,0.873,27,1.388,37,1.609,39,1.646,41,0.817,46,1.605,47,1.378,51,2.023,57,1.489,66,1.562,73,1.274,79,0.983,90,1.232,93,2.043,102,1.388,103,2.694,105,1.232,165,1.747,166,1.092,172,1.157,175,2.043,208,2.043,210,0.936,219,1.747,226,1.874,229,1.646,243,1.062,246,1.489,254,2.541,256,1.599,258,1.274,266,1.747,277,2.043,283,4.888,284,1.008,285,1.925,286,3.855,293,0.914,297,4.844,298,0.873,301,1.489,302,1.124,304,1.874,305,2.148,307,2.501,308,1.562,311,2.166,315,2.455,320,1.32,322,2.843,324,1.32,327,1.274,334,1.717,335,2.572,336,2.073,337,0.893,341,4.294,342,2.843,349,1.232,387,1.747,413,2.772,417,2.678,437,3.325,448,1.874,451,1.32,485,1.874,491,1.874,515,3.325,561,1.562,577,1.232,588,1.426,589,1.874,607,1.274,609,1.874,620,1.747,634,1.747,714,1.489,732,2.043,770,1.683,788,2.148,799,2.678,812,1.274,819,1.562,822,1.232,828,3.325,834,1.562,858,1.874,859,1.426,872,1.646,903,4.442,967,2.678,992,1.646,993,1.874,995,1.747,1014,2.043,1025,2.678,1045,4.442,1104,1.874,1110,3.855,1115,1.646,1116,3.744,1117,1.874,1118,2.301,1119,2.301,1120,2.301,1121,2.301,1122,2.301,1123,2.301,1124,2.301,1125,5.331,1126,2.301,1127,2.301,1128,2.301,1129,2.301,1130,2.301,1131,2.301,1132,3.744,1133,2.301,1134,2.301,1135,2.301,1136,3.744,1137,2.301,1138,2.301,1139,2.301,1140,2.301,1141,2.301,1142,2.301,1143,2.301,1144,2.301,1145,2.301,1146,2.301,1147,3.744,1148,2.301,1149,2.301,1150,2.301,1151,1.874,1152,3.744,1153,2.301,1154,2.043,1155,2.301,1156,2.301,1157,2.301,1158,2.301,1159,2.301]],["tags/58",[]],["title/59",[58,1.421,62,0.696,63,1.389,69,1.194,92,1.194]],["content/59",[5,2.259,103,2.924,301,4.767,1095,6.539,1096,5.996]],["tags/59",[]],["title/60",[30,1.264,778,1.394,783,3.521]],["content/60",[1,1.704,13,3.461,26,2.371,27,2.318,30,2.277,46,1.671,47,1.769,62,1.188,79,2.67,138,2.267,298,2.371,307,2.604,334,2.267,558,4.047,746,3.723,778,2.317,926,5.09,978,5.09,1160,5.09,1161,6.251]],["tags/60",[778,0.8]],["title/61",[413,2.919]],["content/61",[26,2.532,27,2.974,75,3.976,275,5.436,334,2.421,337,2.59,859,4.972,872,4.775,906,4.775,1160,6.531,1162,6.675,1163,6.675,1164,6.675]],["tags/61",[]],["title/62",[26,2.397]],["content/62",[]],["tags/62",[]],["title/63",[30,1.458,288,3.827]],["content/63",[1,1.952,55,2.913,242,4.636,784,3.497,789,3.714,792,5.123,1055,6.808]],["tags/63",[]],["title/64",[285,2.176,1165,5.349]],["content/64",[3,1.681,8,1.334,36,4.656,103,2.585,313,2.927,350,2.712,393,5.301,778,1.957,1166,8.842,1167,7.899,1168,6.509,1169,5.301,1170,5.781,1171,6.509]],["tags/64",[]],["title/65",[285,2.176,859,3.316]],["content/65",[46,1.712,47,1.795,337,3.034,340,4.581,398,2.9,451,4.843,607,3.546,778,2.351,822,3.429,1172,6.403,1173,6.403,1174,6.945,1175,4.862,1176,6.403]],["tags/65",[]],["title/66",[293,1.842,327,2.568,345,2.66]],["content/66",[1,0.841,3,1.939,8,0.633,30,1.287,35,3.285,37,1.049,46,1.262,47,1.084,48,1.119,61,2.184,62,0.586,79,1.318,100,1.352,103,1.875,217,2.741,248,1.913,259,2.208,285,1.255,294,3.205,306,2.709,311,1.875,315,1.601,316,2.343,327,1.709,334,1.119,336,1.709,345,2.709,350,1.967,384,1.653,421,2.18,432,2.741,443,2.343,503,2.741,595,2.343,611,3.845,638,3.982,714,1.998,774,1.653,778,2.081,786,2.095,789,2.449,826,2.741,859,1.913,880,2.513,993,5.637,1003,2.513,1104,3.845,1170,2.741,1177,3.086,1178,3.086,1179,3.086,1180,3.086,1181,3.086,1182,3.086,1183,3.086,1184,2.741,1185,3.086,1186,3.086,1187,3.086,1188,3.086,1189,5.734,1190,3.086,1191,3.086,1192,6.147,1193,6.423,1194,4.721,1195,4.721,1196,4.721,1197,4.721,1198,3.086,1199,3.086,1200,3.086,1201,4.721,1202,3.086,1203,2.741,1204,5.734,1205,3.086,1206,3.086,1207,3.086,1208,3.086,1209,3.086,1210,3.086,1211,3.086,1212,3.086,1213,3.086]],["tags/66",[]],["title/67",[58,1.421,62,0.696,63,1.389,69,1.194,92,1.194]],["content/67",[5,2.28,30,2.026,778,2.235,783,5.643]],["tags/67",[]],["title/91",[1214,5.148]],["content/91",[]],["tags/91",[778,0.346,1214,0.937,1215,1.151]],["title/92",[962,4.8]],["content/92",[1,1.45,18,2.113,30,1.45,31,4.333,46,1.86,47,1.597,48,1.93,50,3.127,62,1.011,73,2.946,90,2.849,92,1.735,139,4.04,246,3.444,249,4.333,263,2.598,346,3.444,577,2.849,607,3.852,619,3.806,645,4.333,746,3.169,755,3.444,805,2.392,926,4.333,992,3.806,1214,4.333,1216,5.32,1217,5.32,1218,5.32,1219,4.503,1220,5.32,1221,5.32,1222,5.32,1223,4.725,1224,4.725,1225,5.32,1226,5.32,1227,5.32,1228,4.725,1229,5.32]],["tags/92",[]],["title/93",[335,2.397]],["content/93",[1,1.754,3,1.843,5,0.951,16,2.006,18,1.881,27,1.149,30,1.291,37,1.955,41,1.1,46,1.537,47,1.592,48,1.718,51,1.756,55,1.926,61,1.61,62,0.9,69,1.544,73,2.622,90,1.659,91,0.753,94,1.471,103,2.283,105,1.659,116,1.845,193,2.523,210,1.926,242,2.006,244,1.716,246,2.006,260,1.921,262,1.716,284,1.357,285,1.26,295,1.921,306,1.777,310,2.523,311,1.881,312,1.513,313,1.393,334,1.718,335,2.18,337,1.202,350,2.395,384,1.659,413,1.431,451,1.777,466,2.353,544,1.921,551,2.752,683,1.513,709,2.752,746,1.845,773,2.353,778,2.085,789,2.981,792,2.216,797,2.006,816,1.845,817,2.821,821,3.297,823,2.006,838,1.716,848,2.103,893,2.752,895,2.752,912,2.821,960,2.523,971,2.523,997,2.006,999,2.523,1022,2.523,1033,2.752,1055,3.856,1060,2.523,1115,2.216,1151,2.523,1219,4.489,1228,4.206,1230,3.098,1231,3.098,1232,3.098,1233,4.364,1234,3.098,1235,4.736,1236,3.098,1237,4.736,1238,3.098,1239,3.098,1240,3.098,1241,2.752]],["tags/93",[]],["title/94",[1242,5.148]],["content/94",[0,2.409,1,0.806,3,2.034,8,0.606,44,1.584,46,1.815,47,1.049,50,1.33,92,0.965,101,3.269,105,1.584,117,2.919,118,2.896,132,3.092,148,3.053,153,2.232,163,1.445,172,1.488,176,1.584,200,2.246,225,2.409,235,2.116,239,3.995,352,2.008,398,2.33,531,2.722,584,1.584,588,1.834,677,1.638,683,1.445,793,2.409,796,2.409,806,1.834,821,1.697,838,1.638,847,3.269,898,3.102,1064,3.722,1219,4.396,1233,2.246,1242,5.845,1243,2.959,1244,2.959,1245,2.246,1246,2.246,1247,2.246,1248,2.627,1249,3.102,1250,2.409,1251,2.409,1252,2.409,1253,2.246,1254,2.246,1255,2.627,1256,6.374,1257,2.627,1258,2.627,1259,4.059,1260,2.627,1261,2.627,1262,2.627,1263,2.627,1264,2.627,1265,2.409,1266,2.627,1267,2.627,1268,2.627,1269,1.915,1270,2.246,1271,2.409,1272,2.409,1273,2.008,1274,2.627]],["tags/94",[]],["title/95",[3,0.871,284,1.792,380,2.058,398,1.517]],["content/95",[1,1.388,3,2.015,8,0.421,18,0.816,20,1.274,24,2.208,32,1.56,44,2.727,46,1.51,47,0.472,50,0.924,54,1.138,55,1.387,62,0.39,71,1.033,75,1.224,91,0.499,105,1.1,117,2.941,118,2.641,132,2.422,138,0.745,148,2.902,153,1.003,155,1.033,163,2.976,172,1.715,176,1.826,244,1.138,254,2.315,284,2.828,295,1.274,305,1.178,312,1.003,336,1.138,349,1.1,352,1.394,380,2.561,398,2.26,412,2.031,421,0.949,531,2.031,553,1.47,554,1.56,557,3.562,584,2.727,595,1.56,628,1.56,646,1.1,677,1.889,678,1.274,680,1.33,683,1.003,711,1.178,713,1.824,714,2.208,723,2.031,726,1.824,728,1.824,738,2.44,754,2.778,755,1.33,784,1.003,787,2.59,789,1.769,805,2.289,822,1.1,847,2.44,1219,1.33,1245,1.56,1246,1.56,1247,1.56,1249,2.968,1250,1.673,1265,1.673,1269,1.33,1270,2.59,1272,1.673,1273,2.315,1275,1.33,1276,3.029,1277,3.411,1278,3.884,1279,2.054,1280,1.824,1281,2.054,1282,1.673,1283,2.054,1284,2.054,1285,2.054,1286,2.054,1287,1.33,1288,2.054,1289,5.092,1290,2.054,1291,2.054,1292,2.054,1293,2.054,1294,2.054,1295,2.054,1296,2.054,1297,2.054,1298,2.054,1299,2.054,1300,2.054,1301,1.673,1302,2.054,1303,2.054,1304,2.054,1305,3.411,1306,2.054,1307,2.054,1308,1.824,1309,2.054,1310,2.054,1311,3.411,1312,2.054,1313,2.054,1314,1.274,1315,2.054,1316,2.054,1317,2.054,1318,2.054,1319,3.321,1320,2.054,1321,2.054,1322,2.054,1323,1.56,1324,2.054,1325,1.673,1326,1.824]],["tags/95",[]],["title/96",[1219,3.463,1275,3.463]],["content/96",[3,2.036,18,0.675,19,2.039,21,1.053,23,0.807,24,1.1,44,0.91,46,1.578,47,0.874,50,0.764,62,0.323,67,0.941,73,0.941,92,0.554,117,1.833,118,3.601,124,3.225,132,2.109,148,3.204,153,2.202,157,0.644,163,0.83,172,0.855,176,0.91,200,1.29,222,1.29,223,1.384,225,1.384,228,1.509,234,2.892,239,2.724,262,0.941,284,1.273,291,1.1,320,0.975,384,0.91,398,1.412,421,0.785,531,2.685,557,2.367,577,0.91,584,0.91,588,1.053,677,0.941,711,0.975,746,1.012,754,2.367,755,1.1,770,0.764,806,1.802,821,1.667,835,2.892,838,1.609,847,2.079,891,1.509,898,1.973,959,1.384,1064,2.367,1219,3.821,1223,1.509,1224,1.509,1233,2.207,1242,3.671,1245,1.29,1246,1.29,1247,1.29,1248,1.509,1249,3.439,1251,1.384,1252,1.384,1253,1.29,1254,1.29,1255,1.509,1256,4.905,1257,1.509,1258,1.509,1259,2.581,1260,1.509,1261,1.509,1262,1.509,1263,1.509,1264,1.509,1265,1.384,1266,1.509,1267,1.509,1268,1.509,1269,1.1,1270,2.207,1271,1.384,1272,2.367,1273,1.973,1274,1.509,1278,1.509,1308,1.509,1323,2.892,1326,3.382,1327,1.699,1328,1.699,1329,1.699,1330,1.699,1331,1.699,1332,1.509,1333,3.809,1334,1.699,1335,1.699,1336,1.699,1337,2.724,1338,1.699,1339,1.802,1340,1.699,1341,2.367,1342,1.29,1343,1.29,1344,1.509,1345,1.699,1346,2.907,1347,1.699,1348,2.907,1349,1.699,1350,1.699,1351,1.699,1352,1.699,1353,1.699,1354,1.699,1355,1.699,1356,1.699,1357,1.699,1358,1.699,1359,1.699,1360,1.699,1361,2.907,1362,1.699,1363,1.699,1364,1.699,1365,1.699,1366,1.699,1367,1.699,1368,1.699,1369,1.699,1370,1.509,1371,2.907,1372,1.699,1373,1.699,1374,1.699,1375,1.699,1376,1.699,1377,1.699,1378,1.699,1379,1.699,1380,1.699,1381,1.699,1382,1.699,1383,1.509,1384,1.699,1385,1.699,1386,1.29,1387,1.699,1388,1.699,1389,1.699,1390,2.907,1391,1.699,1392,2.907,1393,1.699]],["tags/96",[]],["title/97",[58,1.421,62,0.696,63,1.389,69,1.194,92,1.194]],["content/97",[5,2.259,46,1.968,47,1.69,1219,4.767,1233,5.591]],["tags/97",[]],["title/77",[1394,3.765]],["content/77",[1,1.984,8,1.17,26,2.164,30,2.184,41,2.025,49,3.538,50,2.566,51,2.116,55,2.321,92,1.861,245,3.873,256,2.437,263,2.787,313,2.566,535,4.711,619,4.082,646,3.897,677,3.16,678,4.512,784,2.787,789,2.959,792,4.082,804,4.647,1046,6.525,1394,3.399,1395,5.068,1396,5.706,1397,5.706]],["tags/77",[677,0.637,1394,0.685,1398,1.151]],["title/78",[451,2.347,646,2.191,677,2.266,678,2.537]],["content/78",[1,1.377,3,2.007,7,2.184,8,0.692,13,1.123,16,1.313,18,0.805,21,1.257,23,0.962,24,1.313,27,0.752,30,0.553,37,0.69,41,0.72,46,1.35,48,1.224,51,0.752,73,1.123,84,1.651,91,0.82,100,0.888,106,1.313,117,2.054,144,1.451,148,2.722,153,1.648,155,2.821,157,2.127,163,2.467,210,0.825,211,1.651,239,2.414,252,1.313,265,1.651,272,1.651,284,1.478,288,1.451,293,1.721,306,1.163,307,1.805,309,1.451,313,0.912,327,1.123,334,1.572,337,0.787,352,1.376,380,1.02,387,1.54,394,1.54,398,1.251,409,1.651,441,1.801,446,1.208,451,3.217,466,1.54,475,1.651,524,1.651,544,1.257,553,1.451,580,0.962,589,1.651,597,1.313,634,1.54,646,2.705,647,1.801,677,3.864,678,3.132,680,1.313,683,0.99,711,1.163,731,1.801,738,2.414,748,3.1,770,0.912,779,1.313,784,1.648,786,1.376,788,1.936,789,1.75,805,2.271,817,1.208,822,1.086,847,4.012,850,1.801,898,1.376,912,2.01,942,1.651,945,1.801,954,4.981,1245,3.29,1253,2.562,1254,2.562,1276,4.981,1394,2.01,1399,2.028,1400,2.028,1401,1.801,1402,4.113,1403,2.028,1404,2.028,1405,2.028,1406,2.028,1407,2.028,1408,2.028,1409,2.028,1410,2.028,1411,2.028,1412,1.54,1413,2.028,1414,2.028,1415,1.651,1416,2.028,1417,3.374,1418,2.028,1419,2.028,1420,2.028,1421,2.028,1422,2.028,1423,2.028,1424,2.028,1425,1.651,1426,1.801,1427,3.374,1428,1.651,1429,3.374,1430,2.997,1431,2.997,1432,2.997,1433,3.374,1434,3.374,1435,2.028]],["tags/78",[]],["title/79",[91,1.3,1394,3.186]],["content/79",[3,2.007,8,1.073,18,0.613,32,1.171,41,1.256,44,0.826,46,1.665,47,0.614,48,1.284,51,0.992,54,0.854,55,0.627,56,1.256,62,0.508,88,0.999,91,1.272,117,2.931,118,1.836,132,1.481,138,0.56,148,3.008,153,0.753,157,1.343,163,3.267,166,1.269,172,1.78,176,0.826,210,0.627,223,1.256,235,1.103,263,1.306,288,1.913,302,1.306,306,0.885,307,0.643,312,1.306,313,0.693,335,0.585,337,1.038,357,1.256,364,1.256,380,2.403,531,2.108,535,0.999,577,2.558,582,1.37,584,1.432,615,1.256,646,3.583,648,0.956,677,1.481,678,2.619,711,0.885,714,4.191,733,1.37,738,1.103,755,0.999,770,1.202,779,0.999,889,1.256,921,1.37,946,1.256,999,1.256,1031,1.171,1054,1.37,1094,1.37,1099,1.256,1117,1.256,1246,1.171,1247,1.171,1249,1.815,1250,1.256,1251,1.256,1252,1.256,1253,1.171,1254,1.171,1269,1.731,1270,1.171,1287,0.999,1314,0.956,1323,2.031,1342,1.171,1394,4.099,1425,1.256,1436,1.543,1437,3.144,1438,1.543,1439,1.543,1440,1.543,1441,3.144,1442,1.543,1443,2.674,1444,1.256,1445,1.37,1446,1.37,1447,3.144,1448,3.144,1449,2.375,1450,2.375,1451,3.751,1452,3.144,1453,2.375,1454,2.375,1455,3.144,1456,1.37,1457,1.37,1458,1.37,1459,1.37,1460,1.37,1461,1.37,1462,2.375,1463,2.375,1464,3.751,1465,3.144,1466,1.37,1467,3.54,1468,1.543,1469,1.543,1470,3.54,1471,1.543,1472,1.543,1473,2.674,1474,1.543,1475,3.54,1476,2.674,1477,3.54,1478,1.171,1479,3.54,1480,2.674,1481,3.54,1482,1.543,1483,1.543,1484,2.178,1485,1.37,1486,1.37,1487,1.256,1488,1.256,1489,1.256,1490,2.674,1491,1.543,1492,1.543,1493,1.256,1494,1.37,1495,1.543,1496,1.543,1497,1.543,1498,1.543,1499,1.543,1500,1.543,1501,2.674,1502,1.543,1503,1.543,1504,1.543,1505,1.543,1506,1.543,1507,1.543,1508,1.543,1509,1.543,1510,1.543]],["tags/79",[]],["title/80",[1428,5.148]],["content/80",[1,0.527,3,1.983,8,0.665,37,0.657,46,0.867,47,0.444,48,1.981,50,0.869,51,0.717,73,1.07,91,1.017,96,1.468,103,1.288,117,2.554,143,1.717,148,3.079,153,0.944,155,0.972,163,3.066,172,0.972,191,1.574,245,1.312,285,0.786,288,1.383,305,1.109,313,0.869,315,1.003,324,1.109,334,0.701,335,0.733,337,0.75,345,1.109,350,0.805,356,1.383,362,1.383,380,2.106,381,1.717,398,1.818,413,1.497,446,1.151,451,1.109,535,1.251,544,1.198,561,1.312,577,1.736,580,0.918,591,1.717,646,1.736,648,1.198,677,1.07,678,1.198,703,1.468,714,3.535,748,1.383,770,0.869,803,1.198,822,1.035,890,1.717,968,1.468,976,1.312,988,2.462,1022,1.574,1045,1.574,1048,3.179,1051,2.462,1053,2.099,1058,1.574,1083,1.717,1099,1.574,1174,4.353,1339,1.198,1394,3.924,1415,1.574,1425,2.64,1426,2.879,1428,5.365,1430,2.879,1431,1.717,1432,1.717,1437,1.717,1441,2.879,1445,2.879,1446,1.717,1447,3.719,1448,3.719,1449,2.879,1450,1.717,1451,1.717,1452,1.717,1453,1.717,1454,2.879,1455,3.719,1456,1.717,1457,1.717,1458,1.717,1459,1.717,1460,1.717,1461,1.717,1462,1.717,1463,2.879,1464,1.717,1465,1.717,1466,1.717,1484,1.574,1485,1.717,1486,1.717,1487,1.574,1488,1.574,1489,1.574,1511,1.933,1512,1.574,1513,3.242,1514,1.933,1515,1.933,1516,3.242,1517,2.879,1518,3.242,1519,3.242,1520,1.933,1521,3.242,1522,3.242,1523,1.933,1524,1.933,1525,3.242,1526,1.933,1527,1.933,1528,3.242,1529,1.933,1530,4.902,1531,1.933,1532,1.383,1533,1.933,1534,1.933,1535,1.933,1536,1.933,1537,1.574,1538,1.933,1539,1.468,1540,1.933,1541,1.717,1542,1.933,1543,1.933,1544,3.242,1545,1.717,1546,1.933,1547,1.933,1548,1.717,1549,1.933,1550,1.933,1551,1.933,1552,2.879,1553,1.717,1554,2.879,1555,1.717,1556,3.242,1557,1.933,1558,1.933,1559,1.933,1560,1.933]],["tags/80",[]],["title/81",[1053,3.463,1402,4.356]],["content/81",[27,2.68,335,2.741,912,4.305,1115,5.17,1394,4.305,1402,5.886,1561,7.227]],["tags/81",[]],["title/82",[58,1.421,62,0.696,63,1.389,69,1.194,92,1.194]],["content/82",[5,2.324,1394,4.512]],["tags/82",[]],["title/74",[1,1.115,241,2.347,1562,3.332,1563,3.332]],["content/74",[]],["tags/74",[256,0.686,257,1.427]],["title/75",[307,1.932,1562,3.776,1563,3.776]],["content/75",[1,1.122,3,1.917,8,1.05,19,2.204,23,1.229,26,1.943,46,1.1,47,0.945,61,1.985,79,1.106,138,0.939,210,3.003,241,1.485,243,2.366,268,1.757,273,1.965,287,2.108,306,4.236,307,1.078,311,1.028,312,1.264,313,2.865,314,2.299,315,2.657,316,5.152,317,2.299,318,2.299,319,2.108,320,2.361,321,3.352,322,3.891,323,4.173,324,3.349,325,5.794,326,4.755,327,3.757,328,3.891,329,3.665,330,3.665,331,3.891,332,3.891,333,3.891,334,2.581,335,1.943,336,3.528,337,1.988,338,2.108,339,1.757,340,4.177,341,1.852,342,1.965,343,2.299,344,2.299,345,2.361,346,1.676,347,2.108,348,2.794,356,1.852,421,1.195,453,2.299,496,1.852,499,4.55,524,2.108,537,2.299,784,2.851,786,2.794,787,1.965,852,4.173,1564,4.116,1565,2.588,1566,2.588,1567,2.588,1568,2.588,1569,2.588,1570,2.588,1571,2.299,1572,2.588]],["tags/75",[]],["title/76",[58,1.421,62,0.696,63,1.389,69,1.194,92,1.194]],["content/76",[1,2.007,5,2.259,241,4.224,1562,5.996,1563,5.996]],["tags/76",[]],["title/131",[8,0.679,46,0.886,47,0.76,1314,2.054,1573,1.774,1574,1.973]],["content/131",[8,0.99,18,2.591,32,3.668,41,1.714,44,2.586,46,1.744,47,1.497,49,2.995,50,2.172,71,3.281,75,2.877,100,3.728,105,2.586,118,2.505,155,2.429,157,2.801,166,2.293,243,2.23,256,2.063,274,2.877,293,1.918,412,4.399,580,3.096,607,2.675,822,2.586,1034,4.953,1175,3.668,1275,4.223,1314,4.044,1532,3.455,1573,2.586,1574,3.885,1575,4.09,1576,4.29,1577,3.668,1578,4.83,1579,4.83,1580,4.83,1581,4.83,1582,4.83,1583,4.83]],["tags/131",[547,0.781,1573,0.616,1575,0.637]],["title/132",[172,2.691,335,2.029]],["content/132",[1,1.301,3,1.016,8,0.978,13,2.642,16,3.089,23,2.265,26,1.81,27,1.77,35,2.265,46,2.319,47,1.991,54,2.642,91,1.572,116,2.842,210,2.631,246,3.089,260,2.958,262,3.582,307,1.988,312,2.33,315,2.475,327,2.642,335,2.984,337,2.51,348,3.239,607,2.642,620,3.623,683,2.33,778,1.435,1115,3.413,1314,2.958,1574,2.842,1584,3.623,1585,4.772,1586,5.977,1587,6.518,1588,7.34,1589,4.772]],["tags/132",[]],["title/133",[41,1.299,157,1.389,307,1.525,320,2.1,1590,3.661]],["content/133",[3,2.017,18,2.272,35,1.459,41,1.671,44,2.521,46,1.529,47,0.706,49,1.906,50,2.572,55,1.914,79,1.313,91,0.747,100,1.347,117,2.326,118,3.324,148,2.572,153,2.299,155,2.877,156,2.73,157,2.169,163,2.793,166,1.459,218,3.882,284,1.347,307,1.961,421,1.42,452,3.574,584,2.521,615,2.503,648,1.906,683,1.501,745,2.73,788,1.764,817,1.831,838,1.702,940,2.73,1154,2.73,1269,1.99,1337,4.585,1412,2.334,1573,3.432,1574,1.831,1575,3.826,1587,2.73,1591,2.73,1592,3.074,1593,3.074,1594,3.074,1595,2.334,1596,4.092,1597,2.334,1598,4.351,1599,3.367,1600,2.199,1601,2.199,1602,2.334,1603,2.334,1604,2.334,1605,2.334,1606,2.334,1607,2.334,1608,2.334,1609,2.334,1610,2.503,1611,2.503,1612,2.503,1613,2.503,1614,3.833,1615,2.503,1616,2.503,1617,2.503,1618,2.503]],["tags/133",[]],["title/134",[55,1.347,91,0.805,155,1.666,580,1.572,819,2.248,1575,1.834]],["content/134",[19,3.605,26,2.553,35,3.195,90,3.605,100,2.949,102,2.497,284,2.949,770,3.027,799,4.816,803,4.174,1012,4.358,1053,4.358,1573,3.605,1575,3.728,1619,6.732]],["tags/134",[]],["title/135",[91,0.994,1339,2.537,1620,4.091,1621,3.634]],["content/135",[3,1.933,90,3.515,91,1.595,102,2.434,683,3.205,1339,4.069,1573,3.515,1575,3.635,1598,4.455,1621,5.829,1622,6.564,1623,4.984,1624,4.984,1625,4.984]],["tags/135",[]],["title/136",[91,1.3,155,2.691]],["content/136",[3,1.948,8,1.096,18,2.124,44,1.951,55,2.175,79,1.556,91,0.885,100,3.057,102,1.351,132,2.018,148,1.638,155,3.51,163,1.78,166,3.988,167,2.968,194,2.968,256,1.556,274,3.185,303,2.767,313,1.638,324,2.09,384,1.951,421,1.683,446,2.17,558,2.359,573,2.968,580,1.73,584,1.951,611,2.968,624,3.462,626,3.236,629,2.968,723,4.627,799,2.607,840,3.236,1012,3.462,1053,2.359,1071,2.607,1080,4.355,1086,2.473,1275,2.359,1282,4.355,1412,2.767,1532,2.607,1573,3.392,1575,2.018,1596,2.607,1598,2.473,1599,2.607,1600,2.607,1601,3.825,1626,3.644,1627,3.236,1628,3.644,1629,5.347,1630,4.531,1631,3.236,1632,3.644,1633,4.81,1634,3.644,1635,2.767,1636,2.767]],["tags/136",[]],["title/137",[91,0.89,100,1.604,274,2.181,1275,2.37,1637,3.661]],["content/137",[3,1.912,8,1.205,18,2.334,50,2.642,81,5.304,91,1.428,100,2.574,148,2.642,166,2.79,274,3.5,284,2.574,308,3.989,328,4.462,723,3.5,1275,3.805,1575,3.254,1630,4.204,1638,5.219,1639,5.877,1640,4.462,1641,4.462,1642,4.462,1643,4.462,1644,4.462,1645,4.462,1646,4.462]],["tags/137",[]],["title/138",[26,1.759,284,2.031,1647,4.637]],["content/138",[3,2.042,44,1.136,46,1.196,47,0.487,50,0.953,65,2.267,81,1.517,100,1.534,117,1.819,118,2.32,148,2.584,153,1.71,155,1.761,163,2.184,166,3.47,218,2.377,274,1.263,384,1.136,387,1.61,584,1.875,624,3.721,723,3.686,817,1.263,838,1.174,1012,2.267,1071,1.517,1086,1.439,1184,1.883,1337,3.2,1339,2.171,1386,3.396,1573,3.314,1575,2.477,1595,1.61,1596,3.2,1597,1.61,1598,3.036,1599,2.505,1600,1.517,1601,1.517,1602,1.61,1603,1.61,1604,1.61,1605,1.61,1606,1.61,1607,1.61,1608,1.61,1609,1.61,1610,1.727,1611,1.727,1612,1.727,1613,3.643,1614,5.04,1615,3.643,1616,3.643,1617,3.643,1618,3.643,1623,1.61,1624,1.61,1625,1.61,1630,2.505,1631,1.883,1633,2.659,1635,1.61,1636,1.61,1640,1.61,1641,1.61,1642,1.61,1643,1.61,1644,1.61,1645,1.61,1646,1.61,1648,2.121,1649,1.727,1650,1.883,1651,1.883,1652,1.883,1653,1.883,1654,1.883,1655,1.883,1656,1.883,1657,4.473,1658,4.473,1659,4.473,1660,4.473,1661,4.473,1662,4.473,1663,4.473,1664,4.473,1665,4.473,1666,3.972,1667,3.972,1668,3.643,1669,1.883,1670,1.883]],["tags/138",[]],["title/139",[91,0.994,157,1.552,834,2.777,1574,2.437]],["content/139",[18,2.769,19,3.733,26,2.644,62,1.324,138,2.529,157,2.644,452,5.293,475,5.677,1412,5.293,1671,5.293,1672,6.971]],["tags/139",[]],["title/140",[91,1.3,1673,4.751]],["content/140",[3,1.952,8,1.17,51,2.116,91,1.387,117,2.321,153,2.787,157,2.164,307,2.378,393,4.647,577,3.056,648,3.538,1484,4.647,1487,4.647,1488,4.647,1489,4.647,1552,6.463,1553,5.068,1554,6.463,1555,5.068,1574,3.399,1584,4.333,1671,4.333,1673,7.116,1674,5.706,1675,5.706]],["tags/140",[]],["title/141",[91,0.994,157,1.552,246,2.649,1573,2.191]],["content/141",[3,2.055,44,1.035,46,1.31,47,0.744,50,1.458,51,0.717,81,1.383,91,0.47,100,1.834,117,1.993,118,2.171,148,2.823,153,1.583,155,2.746,157,0.733,163,2.045,166,2.805,172,0.972,218,2.842,222,1.468,263,0.944,280,1.383,384,1.035,531,1.931,547,1.312,580,0.918,581,1.312,584,1.736,624,1.251,723,3.52,770,0.869,806,1.198,817,1.151,838,1.07,1012,3.173,1071,1.383,1086,2.842,1249,2.842,1273,1.312,1275,1.251,1314,2.01,1319,1.468,1325,2.64,1337,2.995,1339,2.596,1341,2.64,1342,1.468,1343,1.468,1344,1.717,1386,1.468,1478,2.462,1573,1.736,1574,1.151,1575,2.319,1577,3.179,1584,1.468,1595,1.468,1596,2.995,1597,1.468,1598,2.842,1599,2.319,1600,1.383,1601,1.383,1602,1.468,1603,1.468,1604,1.468,1605,1.468,1606,1.468,1607,1.468,1608,1.468,1609,1.468,1623,1.468,1624,1.468,1625,1.468,1630,2.319,1633,2.462,1635,1.468,1636,1.468,1640,1.468,1641,1.468,1642,1.468,1643,1.468,1644,2.462,1645,1.468,1646,1.468,1649,1.574,1668,1.574,1671,3.179,1676,2.879,1677,2.879,1678,4.353,1679,1.933,1680,1.717,1681,1.717,1682,1.933,1683,1.933,1684,3.719,1685,3.719,1686,1.717,1687,1.717,1688,1.717,1689,1.717,1690,1.717,1691,1.717,1692,1.717,1693,1.717,1694,1.717,1695,1.717,1696,1.717,1697,1.717,1698,1.717,1699,1.717,1700,1.717,1701,1.717,1702,1.717,1703,1.717,1704,1.717,1705,1.717,1706,1.717,1707,1.717,1708,1.717,1709,1.717,1710,1.717,1711,1.933]],["tags/141",[]],["title/142",[62,0.529,91,0.676,100,1.219,229,1.991,274,1.657,646,1.49,755,1.802,1532,1.991]],["content/142",[3,2.055,23,0.669,26,0.535,44,0.755,46,1.061,47,0.568,50,2.029,62,0.268,65,1.601,81,1.008,88,0.913,91,0.343,100,1.447,117,2.313,118,1.713,148,2.9,153,1.938,155,2.27,163,1.613,166,3.316,172,0.709,218,2.241,222,1.07,274,1.473,285,0.573,308,0.957,384,0.755,531,1.967,581,0.957,584,1.324,624,2.922,646,0.755,723,3.19,755,0.913,799,1.008,817,0.84,838,0.781,855,1.148,923,1.008,1012,2.922,1071,1.008,1086,2.241,1249,2.241,1273,0.957,1314,1.533,1319,1.07,1323,1.07,1325,2.013,1337,2.362,1339,2.047,1341,2.013,1342,1.07,1343,1.07,1386,2.507,1478,1.877,1493,1.148,1532,1.008,1573,2.417,1574,1.967,1575,1.829,1577,3.013,1584,1.07,1595,1.07,1596,2.362,1597,1.07,1598,2.241,1599,1.769,1600,1.008,1601,1.008,1602,1.07,1603,1.07,1604,1.07,1605,1.07,1606,1.07,1607,1.07,1608,1.07,1609,1.07,1610,1.148,1611,1.148,1612,1.148,1613,2.013,1614,3.231,1615,2.013,1616,2.013,1617,2.013,1618,2.013,1623,1.07,1624,1.07,1625,1.07,1630,1.769,1633,1.877,1635,1.07,1636,1.07,1640,1.07,1641,1.07,1642,1.07,1643,1.07,1644,1.877,1645,1.07,1646,1.07,1649,1.148,1650,1.252,1651,1.252,1652,1.252,1653,1.252,1654,1.252,1655,1.252,1656,1.252,1666,2.196,1667,2.196,1668,3.231,1669,1.252,1670,1.252,1671,2.507,1676,2.196,1677,2.196,1678,3.524,1680,1.252,1681,1.252,1684,2.933,1685,3.524,1686,1.252,1687,1.252,1688,1.252,1689,1.252,1690,1.252,1691,1.252,1692,1.252,1693,1.252,1694,1.252,1695,1.252,1696,1.252,1697,1.252,1698,2.196,1699,1.252,1700,1.252,1701,1.252,1702,1.252,1703,1.252,1704,1.252,1705,1.252,1706,1.252,1707,1.252,1708,1.252,1709,1.252,1710,1.252,1712,1.41,1713,1.41,1714,2.472,1715,1.41,1716,1.41,1717,1.41,1718,1.41,1719,2.472,1720,1.41,1721,3.302,1722,1.41,1723,1.41,1724,1.41,1725,2.472,1726,2.472,1727,2.472,1728,2.472,1729,2.472,1730,1.41]],["tags/142",[]],["title/143",[58,1.421,62,0.696,63,1.389,69,1.194,92,1.194]],["content/143",[5,2.217,8,1.481,46,1.932,47,1.659,1314,4.481,1573,3.87,1574,4.305]],["tags/143",[]],["title/83",[778,1.609,1444,4.356]],["content/83",[30,1.789,37,2.232,47,1.507,62,1.247,75,3.909,138,2.381,256,2.803,284,2.875,294,4.455,346,4.249,449,5.829,775,5.345,778,1.974,812,3.635,822,3.515,912,3.909,1160,5.345,1169,5.345]],["tags/83",[778,0.483,1731,1.607]],["title/84",[782,5.614]],["content/84",[5,1.464,8,0.978,13,2.642,21,2.958,22,2.33,27,1.77,30,1.763,33,3.413,35,2.265,37,2.797,47,1.095,51,2.399,54,3.582,100,2.09,102,1.77,103,1.895,165,3.623,210,1.941,250,3.886,258,2.642,260,4.011,267,3.413,298,1.81,302,3.159,303,3.623,335,2.984,349,2.555,350,1.988,501,4.238,544,2.958,744,4.238,774,3.93,778,2.207,783,3.623,784,3.159,785,4.238,786,3.239,787,3.623,823,3.089,824,3.886,877,4.238,1060,3.886,1125,4.238,1732,4.772,1733,4.772,1734,4.772]],["tags/84",[]],["title/85",[26,2.397]],["content/85",[]],["tags/85",[]],["title/86",[30,1.264,172,2.332,243,2.141]],["content/86",[3,1.542,27,2.101,30,2.371,37,1.926,41,2.011,91,1.377,311,2.25,334,2.055,337,2.198,410,4.614,588,4.951,774,4.507,778,1.704,779,3.668,788,3.25,790,5.031,797,3.668,984,4.614,1053,3.668,1735,4.614,1736,5.665,1737,5.665,1738,5.665,1739,5.665,1740,5.665,1741,5.665,1742,5.665]],["tags/86",[]],["title/87",[37,1.577,320,2.66,802,2.66]],["content/87",[3,2.036,37,2.397,311,2.157,315,2.816,350,2.263,384,4.191,674,3.686,784,2.652,800,4.123,802,3.115,803,3.367,804,4.422,805,2.441,806,4.37,810,5.74,812,3.007,813,6.26,814,4.422,816,3.234,818,4.823,1743,5.431]],["tags/87",[]],["title/88",[37,1.577,334,1.682,819,3.147]],["content/88",[8,1.069,30,1.421,37,2.881,48,2.49,103,2.071,116,3.106,263,2.546,305,2.991,307,2.173,339,4.659,350,2.173,401,3.376,402,3.539,729,3.539,760,3.73,774,4.366,788,4.402,802,4.402,806,4.757,808,5.59,823,4.968,861,4.631,995,3.959,1269,3.376,1744,5.215,1745,5.215,1746,5.215,1747,5.215,1748,5.215,1749,4.631,1750,5.215]],["tags/88",[]],["title/89",[334,1.484,812,2.266,834,2.777,1735,3.332]],["content/89",[8,0.827,22,1.971,27,1.497,35,4.019,37,1.958,48,2.089,62,1.094,90,2.162,91,0.981,92,1.317,102,1.497,103,1.603,116,2.404,138,1.464,210,1.642,298,2.184,302,1.971,327,2.235,334,1.464,335,2.184,336,2.235,337,1.566,339,2.74,345,3.304,349,2.162,350,2.399,410,4.69,683,1.971,770,1.815,778,2.42,784,1.971,803,2.503,808,3.287,812,3.189,816,3.43,820,5.114,821,3.304,823,2.613,849,3.065,859,2.503,923,2.888,968,3.065,988,3.065,997,2.613,1002,3.287,1203,3.585,1241,3.585,1415,3.287,1512,3.287,1537,3.287,1548,3.585,1627,3.585,1735,4.69,1749,3.585,1751,4.037,1752,4.037,1753,4.037,1754,4.037,1755,3.585,1756,4.037,1757,5.759,1758,4.037,1759,4.037,1760,3.585,1761,4.037,1762,4.037,1763,3.287]],["tags/89",[]],["title/90",[58,1.421,62,0.696,63,1.389,69,1.194,92,1.194]],["content/90",[5,2.302,778,2.256,1444,6.11]],["tags/90",[]],["title/98",[30,0.824,212,2.297,298,1.147,628,2.297,778,1.398,998,1.875]],["content/98",[1,1.76,8,1.323,30,2.142,41,2.291,47,1.482,51,2.394,248,4.003,256,2.757,298,2.449,346,4.18,775,5.258,778,2.363,805,2.902,998,4.003,1764,6.456,1765,6.456,1766,6.456,1767,6.456]],["tags/98",[778,0.8]],["title/99",[3,0.779,298,1.389,778,1.613,998,2.27]],["content/99",[3,0.834,8,0.803,19,2.097,23,1.859,30,1.536,35,3.133,37,1.916,41,2.342,47,1.829,48,2.394,51,2.09,67,2.169,91,0.952,103,3.038,244,2.169,248,2.428,252,2.535,284,2.891,285,1.593,298,2.137,302,1.912,308,2.658,311,1.555,327,2.169,334,2.774,345,2.247,350,3.187,421,1.808,580,2.675,607,2.169,770,2.533,778,2.572,786,3.825,788,2.247,789,3.744,803,3.493,805,2.533,809,2.974,812,2.169,988,2.974,998,2.428,1031,2.974,1169,4.589,1175,2.974,1280,3.478,1539,2.974,1541,3.478,1768,3.916,1769,3.916,1770,3.916,1771,3.478,1772,3.478,1773,3.916]],["tags/99",[]],["title/100",[3,0.779,298,1.389,778,1.613,998,2.27]],["content/100",[8,1.337,26,1.832,27,1.791,30,2.013,35,2.293,47,1.816,48,2.996,50,2.933,79,2.063,117,1.964,252,3.127,284,2.857,298,2.801,308,4.427,311,2.591,334,2.366,346,3.127,413,2.23,458,4.29,580,3.096,607,3.612,621,3.934,687,4.29,778,2.484,797,3.127,812,2.675,903,3.934,912,2.877,960,3.934,998,2.995,1107,3.934,1269,4.781,1301,3.934,1638,4.29,1774,4.83,1775,4.83]],["tags/100",[]],["title/101",[26,2.397]],["content/101",[1,1.293,35,3.058,46,1.722,47,1.479,51,2.389,95,3.601,103,2.906,118,2.46,166,2.251,210,1.929,298,2.444,315,2.46,327,3.568,329,3.393,345,2.721,350,3.049,412,2.825,413,2.19,439,3.862,607,2.626,703,3.601,778,2.686,789,4.071,803,2.94,823,3.07,848,3.219,872,3.393,1051,3.601,1053,3.07,1058,3.862,1401,4.212,1771,4.212,1772,4.212,1776,6.443,1777,4.743,1778,4.743,1779,4.743,1780,4.743,1781,4.743,1782,4.743,1783,4.743,1784,4.743]],["tags/101",[]],["title/102",[58,1.421,62,0.696,63,1.389,69,1.194,92,1.194]],["content/102",[5,2.217,212,5.488,298,2.741,628,5.488,778,2.527,998,4.481]],["tags/102",[]],["title/115",[311,1.842,698,3.147,1287,3.002]],["content/115",[]],["tags/115",[911,1.09,1287,1.04]],["title/116",[962,4.8]],["content/116",[3,1.806,9,4.716,30,1.578,40,3.749,60,3.59,62,1.1,106,3.749,112,4.986,117,3.281,194,4.716,210,2.355,285,2.355,302,2.828,306,3.322,340,5.254,558,3.749,698,3.93,1301,4.716,1539,4.397,1571,5.142,1785,5.142,1786,7.345,1787,5.79,1788,5.142,1789,5.79,1790,5.79]],["tags/116",[]],["title/117",[30,1.458,210,2.176]],["content/117",[91,1.756,117,2.939,305,4.146,337,2.804,910,6.418,911,4.906,912,4.305]],["tags/117",[]],["title/118",[285,1.886,311,1.842,1287,3.002]],["content/118",[3,2,27,2.3,48,2.781,71,3.119,91,1.507,341,5.485,558,4.015,698,5.204,773,4.709,906,4.436,1395,5.507,1791,6.201,1792,6.201,1793,6.201]],["tags/118",[]],["title/119",[285,1.886,311,1.842,911,3.147]],["content/119",[3,1.944,27,2.196,48,2.957,71,2.978,91,1.439,117,2.408,305,4.274,312,2.892,558,3.833,788,3.397,873,4.822,906,4.236,911,4.019,912,4.437,914,5.259,1080,4.822,1282,4.822,1794,5.921,1795,5.921,1796,5.921,1797,5.921]],["tags/119",[]],["title/120",[61,1.577,157,1.759,1798,4.637]],["content/120",[3,1.98,22,2.16,48,1.604,62,1.167,69,1.442,71,2.224,92,1.442,102,1.64,117,3.579,132,3.4,157,2.675,293,1.757,330,3.164,337,2.383,357,3.602,398,2.277,413,2.042,417,3.164,597,3.975,683,2.16,772,3.928,822,2.368,833,3.928,959,3.602,1273,4.168,1493,5.001,1494,5.454,1577,4.663,1785,3.928,1788,3.928,1799,4.423,1800,6.141,1801,6.141,1802,6.141,1803,6.141,1804,6.141,1805,4.423]],["tags/120",[]],["title/121",[590,5.148]],["content/121",[244,4.155,698,5.093,1287,4.857]],["tags/121",[]],["title/122",[58,1.421,62,0.696,63,1.389,69,1.194,92,1.194]],["content/122",[5,2.28,311,2.952,698,5.045,1287,4.812]],["tags/122",[]],["title/103",[8,0.62,592,1.958,953,2.297,1806,2.463,1807,2.463,1808,2.297,1809,2.297]],["content/103",[3,2.014,8,0.732,20,2.215,33,1.555,42,1.77,46,1.557,47,0.82,50,1.607,73,1.204,75,1.295,79,0.928,91,0.868,92,0.709,101,1.555,117,1.453,144,1.555,148,2.816,153,1.745,155,1.797,157,1.726,163,1.061,200,1.65,234,1.65,255,2.426,276,1.475,280,1.555,290,2.713,331,1.65,364,3.706,412,2.128,422,2.713,426,1.93,439,1.77,445,1.77,446,2.71,535,1.407,552,1.65,561,3.089,581,2.426,584,1.164,592,5.085,597,1.407,605,1.77,692,2.91,770,0.977,773,1.65,814,1.77,817,1.295,835,1.65,873,2.91,953,3.455,971,1.77,996,1.77,997,1.407,1018,1.93,1025,1.555,1061,3.174,1086,1.475,1101,1.93,1107,1.77,1117,1.77,1151,1.77,1175,1.65,1319,1.65,1383,5.173,1478,1.65,1537,1.77,1539,1.65,1591,1.93,1760,1.93,1806,4.293,1807,1.77,1808,1.65,1809,4.755,1810,2.174,1811,2.174,1812,5.271,1813,2.174,1814,2.174,1815,2.174,1816,2.174,1817,3.574,1818,2.174,1819,4.551,1820,3.574,1821,3.574,1822,2.174,1823,2.174,1824,2.174,1825,3.574,1826,3.574,1827,2.174,1828,2.174,1829,2.174,1830,2.174,1831,2.174,1832,2.174,1833,2.174,1834,2.174,1835,3.574,1836,3.574,1837,2.174,1838,3.574,1839,2.174,1840,2.174,1841,2.174,1842,3.574,1843,2.174,1844,2.174,1845,2.174,1846,3.574,1847,2.174,1848,2.174,1849,2.174,1850,2.174,1851,2.174,1852,1.93,1853,2.174,1854,3.574,1855,2.174,1856,2.174,1857,2.174,1858,2.174,1859,2.174,1860,2.174,1861,2.174,1862,2.174]],["tags/103",[547,0.609,1808,0.681,1809,0.681,1863,0.897]],["title/104",[58,1.421,62,0.696,63,1.389,69,1.194,92,1.194]],["content/104",[5,2.197,8,1.468,592,4.636,953,5.438,1806,5.832,1807,5.832,1808,5.438,1809,5.438]],["tags/104",[]],["title/105",[210,1.347,293,1.316,337,1.285,902,2.37,1864,2.698,1865,2.698]],["content/105",[8,0.772,22,1.839,23,1.788,30,1.493,51,1.397,72,4.179,79,1.608,102,1.397,158,5.257,189,3.345,210,2.626,266,2.86,293,3.221,305,2.161,315,3.676,329,4.618,333,2.86,335,1.428,336,3.575,337,3.34,394,2.86,412,3.845,422,2.86,430,2.335,471,4.865,485,4.461,491,3.067,496,2.694,567,4.461,577,2.933,579,3.345,588,2.335,609,3.067,623,3.345,805,1.693,859,4.395,872,2.694,902,4.618,929,2.86,946,3.067,995,2.86,1032,2.86,1512,3.067,1852,3.345,1864,5.257,1865,6.133,1866,3.766,1867,3.766,1868,6.456,1869,3.766,1870,3.766,1871,3.766,1872,3.766,1873,3.766,1874,3.766,1875,3.766,1876,3.766,1877,3.766,1878,3.766]],["tags/105",[210,0.468,256,0.492,337,0.447]],["title/106",[58,1.421,62,0.696,63,1.389,69,1.194,92,1.194]],["content/106",[5,2.217,210,2.939,293,2.87,337,2.804,902,5.17,1864,5.886,1865,5.886]],["tags/106",[]],["title/107",[8,0.95,398,1.719,546,2.762]],["content/107",[]],["tags/107",[94,0.546,103,0.457,350,0.48]],["title/108",[350,2.634]],["content/108",[]],["tags/108",[]],["title/109",[816,3.765]],["content/109",[3,1.528,8,1.145,13,3.093,22,2.727,40,3.616,62,1.061,94,3.407,102,2.071,124,3.995,138,2.026,244,3.093,271,4.241,276,4.872,285,2.271,298,2.118,302,2.727,421,2.579,482,6.374,648,3.462,812,3.093,816,4.275,965,3.995,1339,3.462,1370,4.96,1763,4.548,1879,4.96,1880,8.371,1881,5.585,1882,5.585,1883,5.585,1884,5.585]],["tags/109",[]],["title/110",[821,3.626]],["content/110",[3,1.101,8,1.399,22,1.701,40,2.255,62,1.172,71,1.752,87,5.024,94,2.928,105,1.865,115,4.684,138,2.476,140,3.093,176,3.303,244,1.928,274,3.08,276,2.364,280,2.491,298,1.321,300,3.927,312,1.701,350,1.451,395,3.093,398,2.288,400,4.593,412,2.074,428,3.093,430,3.206,531,3.674,553,2.491,567,2.836,573,2.836,581,4.187,592,2.255,594,4.212,614,2.364,711,3.917,779,2.255,830,3.093,864,4.684,967,2.491,976,4.187,984,2.836,1003,4.212,1025,2.491,1032,2.644,1332,3.093,1343,2.644,1576,3.093,1586,4.212,1879,7.027,1885,4.593,1886,3.483,1887,3.483,1888,4.212,1889,3.483,1890,3.483,1891,3.483,1892,3.483,1893,5.172,1894,3.483,1895,5.172,1896,4.593,1897,3.483,1898,3.093,1899,6.063,1900,3.483,1901,3.483,1902,3.483,1903,3.483,1904,3.483,1905,3.483,1906,3.093,1907,3.483]],["tags/110",[]],["title/111",[103,2.511]],["content/111",[]],["tags/111",[]],["title/112",[335,1.759,821,2.66,1908,3.521]],["content/112",[3,1.554,7,1.998,8,0.968,20,2.927,27,1.751,39,2.208,54,2.614,59,5.092,62,0.586,67,1.709,69,1.007,71,1.552,79,1.318,87,3.845,89,2.513,94,2.241,138,2.33,176,1.653,210,1.92,218,2.095,243,1.425,254,2.095,271,2.343,276,2.095,280,2.208,296,2.513,298,1.171,300,3.585,302,1.507,311,1.226,313,2.123,324,2.709,335,1.171,349,2.528,380,1.552,398,1.751,430,2.927,445,2.513,448,3.845,459,4.193,547,2.095,561,2.095,563,2.343,566,4.193,572,1.998,580,1.465,581,3.892,592,1.998,594,2.513,627,2.741,648,1.913,671,2.741,711,1.77,714,1.998,746,1.838,819,2.095,821,2.709,835,3.585,864,4.354,923,2.208,929,3.585,967,2.208,976,3.205,1025,3.377,1031,2.343,1034,2.343,1192,5.092,1517,2.741,1545,2.741,1586,2.513,1755,5.704,1763,3.845,1885,2.741,1888,2.513,1896,2.741,1898,2.741,1899,6.746,1908,5.768,1909,3.086,1910,3.086,1911,4.721,1912,3.086,1913,3.086,1914,3.086,1915,3.086,1916,3.086,1917,3.086,1918,3.086,1919,3.086,1920,3.086,1921,3.086,1922,3.086,1923,3.086,1924,2.741,1925,3.086,1926,3.086,1927,3.086,1928,3.086,1929,3.086]],["tags/112",[]],["title/113",[821,2.347,1908,3.107,1930,3.634,1931,3.634]],["content/113",[3,1.507,94,3.727,103,2.172,138,1.984,165,4.152,243,2.525,276,3.712,296,4.453,335,3.15,380,2.75,413,2.525,444,4.856,629,4.453,673,4.453,736,6.288,738,3.912,802,4.062,821,4.062,1012,3.54,1115,3.912,1271,4.453,1888,4.453,1906,4.856,1908,4.152,1924,4.856,1930,4.856,1931,4.856,1932,5.468,1933,5.468,1934,5.468,1935,5.468,1936,5.468,1937,5.468]],["tags/113",[]],["title/114",[58,1.421,62,0.696,63,1.389,69,1.194,92,1.194]],["content/114",[5,2.28,8,1.523,398,2.756,546,4.427]],["tags/114",[]]],"invertedIndex":[["",{"_index":3,"title":{"1":{},"5":{},"95":{},"99":{},"100":{}},"content":{"12":{},"22":{},"23":{},"28":{},"29":{},"30":{},"35":{},"41":{},"47":{},"48":{},"49":{},"51":{},"64":{},"66":{},"71":{},"72":{},"75":{},"78":{},"79":{},"80":{},"86":{},"87":{},"93":{},"94":{},"95":{},"96":{},"99":{},"103":{},"109":{},"110":{},"112":{},"113":{},"116":{},"118":{},"119":{},"120":{},"125":{},"126":{},"127":{},"128":{},"132":{},"133":{},"135":{},"136":{},"137":{},"138":{},"140":{},"141":{},"142":{}},"tags":{}}],["0",{"_index":1478,"title":{},"content":{"79":{},"103":{},"141":{},"142":{}},"tags":{}}],["0.0.1",{"_index":1178,"title":{},"content":{"66":{}},"tags":{}}],["0.3",{"_index":1391,"title":{},"content":{"96":{}},"tags":{}}],["0.60.0",{"_index":1743,"title":{},"content":{"87":{}},"tags":{}}],["0.72.6",{"_index":1783,"title":{},"content":{"101":{}},"tags":{}}],["0.8",{"_index":152,"title":{},"content":{"12":{}},"tags":{}}],["000",{"_index":231,"title":{},"content":{"12":{}},"tags":{}}],["012aaaa3",{"_index":1738,"title":{},"content":{"86":{}},"tags":{}}],["1",{"_index":172,"title":{"46":{},"86":{},"132":{}},"content":{"12":{},"17":{},"23":{},"58":{},"79":{},"80":{},"94":{},"95":{},"96":{},"141":{},"142":{}},"tags":{}}],["1,};const",{"_index":1382,"title":{},"content":{"96":{}},"tags":{}}],["1.0",{"_index":216,"title":{},"content":{"12":{}},"tags":{}}],["1.0.4",{"_index":478,"title":{},"content":{"30":{}},"tags":{}}],["1.1.0",{"_index":477,"title":{},"content":{"30":{}},"tags":{}}],["1.18.2",{"_index":1778,"title":{},"content":{"101":{}},"tags":{}}],["1.2",{"_index":150,"title":{},"content":{"12":{}},"tags":{}}],["1.4.3",{"_index":1780,"title":{},"content":{"101":{}},"tags":{}}],["10",{"_index":226,"title":{},"content":{"12":{},"48":{},"58":{}},"tags":{}}],["10.1.0",{"_index":483,"title":{},"content":{"30":{}},"tags":{}}],["100",{"_index":234,"title":{},"content":{"12":{},"96":{},"103":{},"127":{}},"tags":{}}],["10000",{"_index":693,"title":{},"content":{"22":{}},"tags":{}}],["11",{"_index":141,"title":{},"content":{"12":{},"126":{}},"tags":{}}],["11.0",{"_index":467,"title":{},"content":{"30":{}},"tags":{}}],["11.4.0",{"_index":1781,"title":{},"content":{"101":{}},"tags":{}}],["12",{"_index":1100,"title":{},"content":{"56":{}},"tags":{}}],["13",{"_index":1355,"title":{},"content":{"96":{}},"tags":{}}],["14",{"_index":1213,"title":{},"content":{"66":{}},"tags":{}}],["14.3.0",{"_index":1782,"title":{},"content":{"101":{}},"tags":{}}],["140",{"_index":1390,"title":{},"content":{"96":{}},"tags":{}}],["16.2",{"_index":1004,"title":{},"content":{"126":{}},"tags":{}}],["180",{"_index":1041,"title":{},"content":{"127":{}},"tags":{}}],["189",{"_index":669,"title":{},"content":{"10":{}},"tags":{}}],["2",{"_index":320,"title":{"47":{},"87":{},"133":{}},"content":{"17":{},"29":{},"30":{},"58":{},"75":{},"96":{},"127":{}},"tags":{}}],["2.0",{"_index":1565,"title":{},"content":{"75":{}},"tags":{}}],["20",{"_index":1271,"title":{},"content":{"94":{},"96":{},"113":{}},"tags":{}}],["257",{"_index":1016,"title":{},"content":{"127":{}},"tags":{}}],["2704",{"_index":1006,"title":{},"content":{"126":{}},"tags":{}}],["2f842489f07a",{"_index":1742,"title":{},"content":{"86":{}},"tags":{}}],["3",{"_index":819,"title":{"48":{},"88":{},"134":{}},"content":{"58":{},"112":{},"127":{}},"tags":{}}],["3.0.0",{"_index":811,"title":{},"content":{"47":{}},"tags":{}}],["3.1.5",{"_index":1403,"title":{},"content":{"78":{}},"tags":{}}],["397327562",{"_index":481,"title":{},"content":{"30":{}},"tags":{}}],["4",{"_index":834,"title":{"49":{},"89":{},"139":{}},"content":{"50":{},"58":{},"127":{}},"tags":{}}],["4.0.5",{"_index":1400,"title":{},"content":{"78":{}},"tags":{}}],["40",{"_index":1028,"title":{},"content":{"127":{}},"tags":{}}],["429b",{"_index":1007,"title":{},"content":{"126":{}},"tags":{}}],["4bae",{"_index":1740,"title":{},"content":{"86":{}},"tags":{}}],["4ce5",{"_index":1739,"title":{},"content":{"86":{}},"tags":{}}],["5",{"_index":229,"title":{"50":{},"142":{}},"content":{"12":{},"51":{},"58":{}},"tags":{}}],["5.3.0",{"_index":1401,"title":{},"content":{"78":{},"101":{}},"tags":{}}],["50",{"_index":540,"title":{},"content":{"30":{}},"tags":{}}],["500",{"_index":1432,"title":{},"content":{"78":{},"80":{}},"tags":{}}],["50000",{"_index":1026,"title":{},"content":{"127":{}},"tags":{}}],["56",{"_index":1704,"title":{},"content":{"141":{},"142":{}},"tags":{}}],["5a269aa1",{"_index":1005,"title":{},"content":{"126":{}},"tags":{}}],["6",{"_index":1134,"title":{},"content":{"58":{}},"tags":{}}],["6.10.2",{"_index":1399,"title":{},"content":{"78":{}},"tags":{}}],["7",{"_index":828,"title":{},"content":{"48":{},"58":{}},"tags":{}}],["8",{"_index":1146,"title":{},"content":{"58":{}},"tags":{}}],["80",{"_index":1870,"title":{},"content":{"105":{}},"tags":{}}],["9",{"_index":1155,"title":{},"content":{"58":{}},"tags":{}}],["9f4d",{"_index":1741,"title":{},"content":{"86":{}},"tags":{}}],["__dev__",{"_index":190,"title":{},"content":{"12":{}},"tags":{}}],["__dirnam",{"_index":1794,"title":{},"content":{"119":{}},"tags":{}}],["_props.navigation.navigate(\"cod",{"_index":1378,"title":{},"content":{"96":{}},"tags":{}}],["aar",{"_index":1096,"title":{"55":{}},"content":{"56":{},"59":{}},"tags":{}}],["abov",{"_index":1571,"title":{},"content":{"75":{},"116":{}},"tags":{}}],["absolut",{"_index":1790,"title":{},"content":{"116":{}},"tags":{}}],["absolute\",};const",{"_index":1384,"title":{},"content":{"96":{}},"tags":{}}],["accept",{"_index":701,"title":{},"content":{"22":{},"48":{}},"tags":{}}],["access",{"_index":94,"title":{"12":{}},"content":{"12":{},"16":{},"18":{},"19":{},"30":{},"72":{},"93":{},"109":{},"110":{},"112":{},"113":{},"127":{}},"tags":{"12":{},"14":{},"107":{}}}],["accessibilityact",{"_index":617,"title":{},"content":{"18":{}},"tags":{}}],["accessibilitylabel",{"_index":1039,"title":{},"content":{"127":{}},"tags":{}}],["accessibl",{"_index":240,"title":{},"content":{"13":{}},"tags":{}}],["accessori",{"_index":1621,"title":{"135":{}},"content":{"135":{}},"tags":{}}],["accomplish",{"_index":28,"title":{},"content":{"2":{},"127":{}},"tags":{}}],["account",{"_index":267,"title":{},"content":{"28":{},"30":{},"44":{},"48":{},"84":{}},"tags":{}}],["achiev",{"_index":895,"title":{},"content":{"51":{},"93":{}},"tags":{}}],["action",{"_index":711,"title":{},"content":{"22":{},"23":{},"78":{},"79":{},"95":{},"96":{},"110":{},"112":{},"126":{},"127":{}},"tags":{}}],["actions((self",{"_index":1293,"title":{},"content":{"95":{}},"tags":{}}],["actions((stor",{"_index":721,"title":{},"content":{"22":{},"23":{}},"tags":{}}],["actions(withsetpropact",{"_index":1292,"title":{},"content":{"95":{}},"tags":{}}],["activ",{"_index":1885,"title":{},"content":{"110":{},"112":{}},"tags":{}}],["activeopacity={1",{"_index":1608,"title":{},"content":{"133":{},"138":{},"141":{},"142":{}},"tags":{}}],["actual",{"_index":193,"title":{},"content":{"12":{},"50":{},"93":{}},"tags":{}}],["ad",{"_index":19,"title":{},"content":{"1":{},"24":{},"29":{},"46":{},"48":{},"75":{},"96":{},"99":{},"126":{},"127":{},"134":{},"139":{}},"tags":{}}],["adapt",{"_index":1754,"title":{},"content":{"89":{}},"tags":{}}],["adb",{"_index":1192,"title":{},"content":{"66":{},"112":{}},"tags":{}}],["add",{"_index":91,"title":{"17":{},"32":{},"79":{},"134":{},"135":{},"136":{},"137":{},"139":{},"140":{},"141":{},"142":{}},"content":{"6":{},"18":{},"23":{},"28":{},"30":{},"33":{},"35":{},"40":{},"46":{},"48":{},"51":{},"70":{},"71":{},"78":{},"79":{},"80":{},"86":{},"89":{},"93":{},"95":{},"99":{},"103":{},"117":{},"118":{},"119":{},"126":{},"127":{},"128":{},"132":{},"133":{},"135":{},"136":{},"137":{},"140":{},"141":{},"142":{}},"tags":{}}],["add_ssh_key",{"_index":442,"title":{},"content":{"30":{}},"tags":{}}],["addcode(cod",{"_index":1294,"title":{},"content":{"95":{}},"tags":{}}],["addit",{"_index":49,"title":{},"content":{"3":{},"29":{},"30":{},"51":{},"52":{},"77":{},"131":{},"133":{}},"tags":{}}],["addition",{"_index":1632,"title":{},"content":{"136":{}},"tags":{}}],["address",{"_index":407,"title":{},"content":{"30":{}},"tags":{}}],["adjac",{"_index":587,"title":{},"content":{"16":{}},"tags":{}}],["adjust",{"_index":1761,"title":{},"content":{"89":{}},"tags":{}}],["adopt",{"_index":1163,"title":{},"content":{"61":{}},"tags":{}}],["advanc",{"_index":299,"title":{},"content":{"28":{}},"tags":{}}],["advand",{"_index":1010,"title":{},"content":{"127":{}},"tags":{}}],["advic",{"_index":636,"title":{},"content":{"19":{}},"tags":{}}],["again",{"_index":873,"title":{},"content":{"50":{},"103":{},"119":{}},"tags":{}}],["against",{"_index":1824,"title":{},"content":{"103":{}},"tags":{}}],["ahead",{"_index":839,"title":{},"content":{"49":{},"127":{}},"tags":{}}],["air",{"_index":776,"title":{},"content":{"43":{},"50":{}},"tags":{}}],["alert",{"_index":891,"title":{},"content":{"51":{},"96":{}},"tags":{}}],["alert.alert(\"cod",{"_index":1362,"title":{},"content":{"96":{}},"tags":{}}],["alignitem",{"_index":1393,"title":{},"content":{"96":{}},"tags":{}}],["allow",{"_index":106,"title":{},"content":{"12":{},"16":{},"28":{},"30":{},"78":{},"116":{},"127":{}},"tags":{}}],["allowfontsc",{"_index":168,"title":{},"content":{"12":{}},"tags":{}}],["allowprovisioningupd",{"_index":378,"title":{},"content":{"30":{}},"tags":{}}],["almostther",{"_index":1078,"title":{},"content":{"41":{}},"tags":{}}],["along",{"_index":53,"title":{},"content":{"3":{},"33":{}},"tags":{}}],["aloud",{"_index":1895,"title":{},"content":{"110":{}},"tags":{}}],["alreadi",{"_index":260,"title":{},"content":{"27":{},"29":{},"44":{},"57":{},"84":{},"93":{},"125":{},"132":{}},"tags":{}}],["alway",{"_index":89,"title":{},"content":{"6":{},"112":{},"127":{}},"tags":{}}],["android",{"_index":103,"title":{"55":{},"111":{}},"content":{"12":{},"46":{},"47":{},"48":{},"56":{},"58":{},"59":{},"64":{},"66":{},"80":{},"84":{},"88":{},"89":{},"93":{},"99":{},"101":{},"113":{},"126":{}},"tags":{"14":{},"55":{},"107":{}}}],["android/gradlew",{"_index":1159,"title":{},"content":{"58":{}},"tags":{}}],["android_ndk_vers",{"_index":1127,"title":{},"content":{"58":{}},"tags":{}}],["androiddrag",{"_index":1758,"title":{},"content":{"89":{}},"tags":{}}],["androidsdk",{"_index":1734,"title":{},"content":{"84":{}},"tags":{}}],["anim",{"_index":1101,"title":{},"content":{"56":{},"103":{}},"tags":{}}],["announc",{"_index":599,"title":{},"content":{"17":{}},"tags":{}}],["anoth",{"_index":586,"title":{},"content":{"16":{},"19":{},"23":{},"56":{},"126":{},"127":{}},"tags":{}}],["answer",{"_index":791,"title":{},"content":{"46":{}},"tags":{}}],["anyon",{"_index":43,"title":{},"content":{"3":{}},"tags":{}}],["anywher",{"_index":1897,"title":{},"content":{"110":{}},"tags":{}}],["api",{"_index":681,"title":{"22":{},"23":{}},"content":{"21":{},"22":{},"23":{},"24":{},"25":{},"41":{}},"tags":{}}],["api.apisauce.setheader(\"author",{"_index":742,"title":{},"content":{"23":{}},"tags":{}}],["apiconfig",{"_index":689,"title":{},"content":{"22":{}},"tags":{}}],["apisauc",{"_index":676,"title":{"21":{}},"content":{"21":{},"22":{},"23":{},"24":{}},"tags":{"21":{}}}],["apisauceinst",{"_index":694,"title":{},"content":{"22":{}},"tags":{}}],["apk",{"_index":808,"title":{},"content":{"47":{},"88":{},"89":{}},"tags":{}}],["app",{"_index":48,"title":{},"content":{"3":{},"8":{},"10":{},"12":{},"16":{},"27":{},"30":{},"41":{},"47":{},"50":{},"51":{},"56":{},"66":{},"71":{},"78":{},"79":{},"80":{},"88":{},"89":{},"92":{},"93":{},"99":{},"100":{},"118":{},"119":{},"120":{},"126":{}},"tags":{}}],["app(prop",{"_index":1534,"title":{},"content":{"80":{}},"tags":{}}],["app.config.j",{"_index":904,"title":{},"content":{"52":{}},"tags":{}}],["app.j",{"_index":1170,"title":{},"content":{"64":{},"66":{}},"tags":{}}],["app.json",{"_index":797,"title":{},"content":{"46":{},"51":{},"52":{},"86":{},"93":{},"100":{},"126":{}},"tags":{}}],["app.tsx",{"_index":1425,"title":{},"content":{"78":{},"79":{},"80":{}},"tags":{}}],["app/**/*.{js,jsx,json,md,ts,tsx",{"_index":1185,"title":{},"content":{"66":{}},"tags":{}}],["app/app.tsx",{"_index":1675,"title":{},"content":{"140":{}},"tags":{}}],["app/compon",{"_index":1250,"title":{},"content":{"79":{},"94":{},"95":{}},"tags":{}}],["app/components\";import",{"_index":1340,"title":{},"content":{"96":{}},"tags":{}}],["app/components/profile.tsx",{"_index":947,"title":{},"content":{"34":{},"35":{}},"tags":{}}],["app/components/selectfield.tsx",{"_index":1592,"title":{},"content":{"133":{}},"tags":{}}],["app/components/spec",{"_index":950,"title":{},"content":{"35":{}},"tags":{}}],["app/components/specs/profile.spec.tsx",{"_index":958,"title":{},"content":{"35":{}},"tags":{}}],["app/model",{"_index":1307,"title":{},"content":{"95":{}},"tags":{}}],["app/models\";import",{"_index":1345,"title":{},"content":{"96":{}},"tags":{}}],["app/models/authenticationstore.t",{"_index":710,"title":{},"content":{"22":{}},"tags":{}}],["app/navig",{"_index":1304,"title":{},"content":{"95":{}},"tags":{}}],["app/screens/demoshowroomscreen.tsx",{"_index":1799,"title":{},"content":{"120":{}},"tags":{}}],["app/screens/loginscreen.tsx",{"_index":753,"title":{},"content":{"23":{},"49":{}},"tags":{}}],["app/services/api",{"_index":737,"title":{},"content":{"23":{}},"tags":{}}],["app/services/api/api.t",{"_index":684,"title":{},"content":{"22":{}},"tags":{}}],["app/store.t",{"_index":1438,"title":{},"content":{"79":{}},"tags":{}}],["app/store/counterslic",{"_index":1498,"title":{},"content":{"79":{}},"tags":{}}],["app/store/stor",{"_index":1497,"title":{},"content":{"79":{}},"tags":{}}],["app/them",{"_index":1308,"title":{},"content":{"95":{},"96":{}},"tags":{}}],["app/utils/storage.tsx",{"_index":1057,"title":{},"content":{"41":{}},"tags":{}}],["appar",{"_index":468,"title":{},"content":{"30":{}},"tags":{}}],["appdispatch",{"_index":1455,"title":{},"content":{"79":{},"80":{}},"tags":{}}],["appear",{"_index":1545,"title":{},"content":{"80":{},"112":{}},"tags":{}}],["appearsonindex={0",{"_index":1695,"title":{},"content":{"141":{},"142":{}},"tags":{}}],["appet",{"_index":782,"title":{"44":{},"84":{}},"content":{},"tags":{}}],["appid",{"_index":982,"title":{},"content":{"126":{},"127":{}},"tags":{}}],["appl",{"_index":408,"title":{},"content":{"30":{}},"tags":{}}],["appli",{"_index":619,"title":{},"content":{"18":{},"50":{},"57":{},"77":{},"92":{}},"tags":{}}],["applic",{"_index":848,"title":{},"content":{"39":{},"49":{},"56":{},"93":{},"101":{},"124":{}},"tags":{}}],["application'",{"_index":1156,"title":{},"content":{"58":{}},"tags":{}}],["application/json",{"_index":702,"title":{},"content":{"22":{}},"tags":{}}],["appnavig",{"_index":1484,"title":{},"content":{"79":{},"80":{},"140":{}},"tags":{}}],["appprop",{"_index":1535,"title":{},"content":{"80":{}},"tags":{}}],["appreci",{"_index":76,"title":{},"content":{"4":{}},"tags":{}}],["approach",{"_index":889,"title":{},"content":{"51":{},"56":{},"79":{}},"tags":{}}],["appropri",{"_index":1759,"title":{},"content":{"89":{}},"tags":{}}],["approxim",{"_index":1827,"title":{},"content":{"103":{}},"tags":{}}],["appstackscreenprop",{"_index":1247,"title":{},"content":{"79":{},"94":{},"95":{},"96":{}},"tags":{}}],["appstackscreenprops<\"cod",{"_index":1310,"title":{},"content":{"95":{}},"tags":{}}],["appstackscreenprops<\"welcom",{"_index":1252,"title":{},"content":{"79":{},"94":{},"96":{}},"tags":{}}],["appstat",{"_index":121,"title":{},"content":{"12":{}},"tags":{}}],["appstate.addeventlistener(\"chang",{"_index":202,"title":{},"content":{"12":{}},"tags":{}}],["appstate.currentst",{"_index":199,"title":{},"content":{"12":{}},"tags":{}}],["appstatevis",{"_index":196,"title":{},"content":{"12":{}},"tags":{}}],["appstor",{"_index":371,"title":{},"content":{"30":{}},"tags":{}}],["arch",{"_index":515,"title":{},"content":{"30":{},"58":{}},"tags":{}}],["architectur",{"_index":1133,"title":{},"content":{"58":{}},"tags":{}}],["archiv",{"_index":1128,"title":{},"content":{"58":{}},"tags":{}}],["area",{"_index":1343,"title":{},"content":{"96":{},"110":{},"141":{},"142":{}},"tags":{}}],["arefontsload",{"_index":1434,"title":{},"content":{"78":{}},"tags":{}}],["aren't",{"_index":612,"title":{},"content":{"18":{}},"tags":{}}],["argument",{"_index":946,"title":{},"content":{"34":{},"79":{},"105":{}},"tags":{}}],["aris",{"_index":1098,"title":{},"content":{"56":{}},"tags":{}}],["arm",{"_index":1132,"title":{},"content":{"58":{}},"tags":{}}],["around",{"_index":445,"title":{},"content":{"30":{},"103":{},"112":{}},"tags":{}}],["array",{"_index":1282,"title":{},"content":{"95":{},"119":{},"136":{}},"tags":{}}],["array.filter((v",{"_index":1715,"title":{},"content":{"142":{}},"tags":{}}],["articl",{"_index":671,"title":{},"content":{"10":{},"112":{}},"tags":{}}],["assert",{"_index":991,"title":{},"content":{"126":{}},"tags":{}}],["assertvis",{"_index":989,"title":{},"content":{"126":{},"127":{}},"tags":{}}],["assist",{"_index":1931,"title":{"113":{}},"content":{"113":{}},"tags":{}}],["associ",{"_index":1035,"title":{},"content":{"127":{}},"tags":{}}],["assum",{"_index":1792,"title":{},"content":{"118":{}},"tags":{}}],["async",{"_index":703,"title":{},"content":{"22":{},"41":{},"80":{},"101":{}},"tags":{}}],["asyncstorag",{"_index":1048,"title":{},"content":{"39":{},"41":{},"80":{}},"tags":{"38":{}}}],["asyncstorage.clear",{"_index":1091,"title":{},"content":{"41":{}},"tags":{}}],["asyncstorage.getitem(key",{"_index":1065,"title":{},"content":{"41":{}},"tags":{}}],["asyncstorage.removeitem(key",{"_index":1087,"title":{},"content":{"41":{}},"tags":{}}],["asyncstorage.setitem(key",{"_index":1072,"title":{},"content":{"41":{}},"tags":{}}],["atl",{"_index":1651,"title":{},"content":{"138":{},"142":{}},"tags":{}}],["attempt",{"_index":1638,"title":{},"content":{"100":{},"137":{}},"tags":{}}],["audit",{"_index":1864,"title":{"105":{}},"content":{"105":{},"106":{}},"tags":{}}],["auth",{"_index":414,"title":{"21":{},"22":{},"23":{}},"content":{"22":{},"23":{},"25":{},"30":{}},"tags":{}}],["authemail",{"_index":719,"title":{},"content":{"22":{},"23":{}},"tags":{}}],["authent",{"_index":679,"title":{},"content":{"21":{},"22":{},"23":{},"126":{}},"tags":{"21":{}}}],["authenticationstor",{"_index":725,"title":{},"content":{"22":{},"23":{}},"tags":{}}],["authenticationstoremodel",{"_index":715,"title":{},"content":{"22":{}},"tags":{}}],["authenticationstoresnapshot",{"_index":727,"title":{},"content":{"22":{}},"tags":{}}],["authstor",{"_index":735,"title":{},"content":{"23":{}},"tags":{}}],["authtoken",{"_index":717,"title":{},"content":{"22":{},"23":{}},"tags":{}}],["auto",{"_index":1200,"title":{},"content":{"66":{}},"tags":{}}],["automat",{"_index":247,"title":{},"content":{"26":{},"32":{}},"tags":{}}],["avail",{"_index":1032,"title":{},"content":{"56":{},"105":{},"110":{},"127":{}},"tags":{}}],["averageitemlength",{"_index":1844,"title":{},"content":{"103":{}},"tags":{}}],["await",{"_index":1064,"title":{},"content":{"41":{},"94":{},"96":{}},"tags":{}}],["awar",{"_index":653,"title":{},"content":{"10":{}},"tags":{}}],["away",{"_index":865,"title":{},"content":{"41":{},"50":{}},"tags":{}}],["babel",{"_index":911,"title":{"119":{}},"content":{"70":{},"71":{},"117":{},"119":{}},"tags":{"115":{}}}],["babel.config.j",{"_index":914,"title":{},"content":{"71":{},"119":{}},"tags":{}}],["babel/plugin",{"_index":916,"title":{},"content":{"71":{}},"tags":{}}],["babelrc",{"_index":915,"title":{},"content":{"71":{}},"tags":{}}],["back",{"_index":24,"title":{"5":{}},"content":{"1":{},"12":{},"78":{},"95":{},"96":{},"127":{}},"tags":{}}],["backdropcomponent={(prop",{"_index":1694,"title":{},"content":{"141":{},"142":{}},"tags":{}}],["backgroundcolor",{"_index":223,"title":{},"content":{"12":{},"79":{},"96":{}},"tags":{}}],["backward",{"_index":1874,"title":{},"content":{"105":{}},"tags":{}}],["barcod",{"_index":1224,"title":{},"content":{"92":{},"96":{}},"tags":{}}],["bare",{"_index":926,"title":{},"content":{"60":{},"71":{},"92":{}},"tags":{}}],["base",{"_index":45,"title":{},"content":{"3":{},"12":{},"18":{}},"tags":{}}],["baseurl",{"_index":698,"title":{"115":{}},"content":{"22":{},"116":{},"118":{},"121":{},"122":{}},"tags":{}}],["bash",{"_index":508,"title":{},"content":{"30":{},"125":{}},"tags":{}}],["basic",{"_index":280,"title":{},"content":{"28":{},"103":{},"110":{},"112":{},"141":{}},"tags":{}}],["be",{"_index":357,"title":{},"content":{"30":{},"79":{},"120":{}},"tags":{}}],["bearer",{"_index":743,"title":{},"content":{"23":{}},"tags":{}}],["befor",{"_index":352,"title":{},"content":{"17":{},"30":{},"78":{},"94":{},"95":{},"127":{}},"tags":{}}],["before_al",{"_index":359,"title":{},"content":{"30":{}},"tags":{}}],["begin",{"_index":1332,"title":{},"content":{"96":{},"110":{}},"tags":{}}],["beginn",{"_index":1894,"title":{},"content":{"110":{}},"tags":{}}],["behav",{"_index":905,"title":{},"content":{"52":{}},"tags":{}}],["behavior",{"_index":887,"title":{},"content":{"51":{}},"tags":{}}],["behind",{"_index":1105,"title":{},"content":{"56":{}},"tags":{}}],["belong",{"_index":15,"title":{},"content":{"1":{}},"tags":{}}],["below",{"_index":309,"title":{},"content":{"29":{},"30":{},"52":{},"57":{},"78":{}},"tags":{}}],["beta",{"_index":251,"title":{},"content":{"26":{},"30":{}},"tags":{}}],["better",{"_index":890,"title":{},"content":{"51":{},"80":{}},"tags":{}}],["between",{"_index":628,"title":{"98":{}},"content":{"19":{},"95":{},"102":{}},"tags":{}}],["bf30",{"_index":1008,"title":{},"content":{"126":{}},"tags":{}}],["big",{"_index":175,"title":{},"content":{"12":{},"58":{}},"tags":{}}],["bigger",{"_index":136,"title":{},"content":{"12":{}},"tags":{}}],["bin/bash",{"_index":486,"title":{},"content":{"30":{}},"tags":{}}],["bin/downloadexpoapp.sh",{"_index":1206,"title":{},"content":{"66":{}},"tags":{}}],["bin/exponent.app",{"_index":1211,"title":{},"content":{"66":{}},"tags":{}}],["bin/postinstal",{"_index":1199,"title":{},"content":{"66":{}},"tags":{}}],["binari",{"_index":1109,"title":{},"content":{"56":{}},"tags":{}}],["binarypath",{"_index":1210,"title":{},"content":{"66":{}},"tags":{}}],["bind",{"_index":921,"title":{},"content":{"71":{},"79":{}},"tags":{}}],["bit",{"_index":1022,"title":{},"content":{"80":{},"93":{},"127":{}},"tags":{}}],["blazer",{"_index":1618,"title":{},"content":{"133":{},"138":{},"142":{}},"tags":{}}],["blog",{"_index":354,"title":{},"content":{"18":{},"30":{}},"tags":{}}],["bo",{"_index":1653,"title":{},"content":{"138":{},"142":{}},"tags":{}}],["boilerpl",{"_index":16,"title":{},"content":{"1":{},"3":{},"21":{},"22":{},"78":{},"93":{},"132":{}},"tags":{}}],["boolean",{"_index":1071,"title":{},"content":{"41":{},"136":{},"138":{},"141":{},"142":{}},"tags":{}}],["boot",{"_index":1241,"title":{},"content":{"89":{},"93":{}},"tags":{}}],["bootsplash",{"_index":1172,"title":{},"content":{"65":{}},"tags":{}}],["bordercolor",{"_index":230,"title":{},"content":{"12":{}},"tags":{}}],["borderradiu",{"_index":228,"title":{},"content":{"12":{},"96":{}},"tags":{}}],["borderwidth",{"_index":232,"title":{},"content":{"12":{}},"tags":{}}],["both",{"_index":746,"title":{},"content":{"23":{},"24":{},"35":{},"46":{},"60":{},"92":{},"93":{},"96":{},"112":{}},"tags":{}}],["bottom",{"_index":1314,"title":{"131":{}},"content":{"79":{},"95":{},"131":{},"132":{},"141":{},"142":{},"143":{}},"tags":{}}],["bottominset={bottom",{"_index":1700,"title":{},"content":{"141":{},"142":{}},"tags":{}}],["bottomsheet",{"_index":1674,"title":{},"content":{"140":{}},"tags":{}}],["bottomsheetbackdrop",{"_index":1676,"title":{},"content":{"141":{},"142":{}},"tags":{}}],["bottomsheetflatlist",{"_index":1677,"title":{},"content":{"141":{},"142":{}},"tags":{}}],["bottomsheetfoot",{"_index":1678,"title":{},"content":{"141":{},"142":{}},"tags":{}}],["bottomsheetmod",{"_index":1671,"title":{},"content":{"139":{},"140":{},"141":{},"142":{}},"tags":{}}],["bottomsheetmodalprovid",{"_index":1673,"title":{"140":{}},"content":{"140":{}},"tags":{}}],["bottomtabnavigationopt",{"_index":128,"title":{},"content":{"12":{}},"tags":{}}],["box",{"_index":465,"title":{},"content":{"30":{}},"tags":{}}],["branch",{"_index":496,"title":{},"content":{"30":{},"50":{},"56":{},"75":{},"105":{}},"tags":{}}],["break",{"_index":146,"title":{},"content":{"12":{}},"tags":{}}],["breez",{"_index":682,"title":{},"content":{"21":{}},"tags":{}}],["brew",{"_index":975,"title":{},"content":{"125":{}},"tags":{}}],["bug",{"_index":879,"title":{},"content":{"50":{},"56":{}},"tags":{}}],["build",{"_index":37,"title":{"47":{},"48":{},"87":{},"88":{}},"content":{"2":{},"3":{},"21":{},"26":{},"28":{},"30":{},"47":{},"48":{},"50":{},"51":{},"53":{},"56":{},"57":{},"58":{},"66":{},"78":{},"80":{},"83":{},"84":{},"86":{},"87":{},"88":{},"89":{},"93":{},"99":{},"126":{}},"tags":{}}],["build/build",{"_index":1753,"title":{},"content":{"89":{}},"tags":{}}],["build:configur",{"_index":790,"title":{},"content":{"46":{},"86":{}},"tags":{}}],["build:detox",{"_index":1202,"title":{},"content":{"66":{}},"tags":{}}],["build_ios_app",{"_index":372,"title":{},"content":{"30":{}},"tags":{}}],["buildtyp",{"_index":807,"title":{},"content":{"47":{}},"tags":{}}],["built",{"_index":1511,"title":{},"content":{"80":{}},"tags":{}}],["bump",{"_index":363,"title":{},"content":{"30":{}},"tags":{}}],["bunch",{"_index":1866,"title":{},"content":{"105":{}},"tags":{}}],["bundl",{"_index":513,"title":{},"content":{"30":{},"47":{}},"tags":{}}],["bundleidentifi",{"_index":985,"title":{},"content":{"126":{}},"tags":{}}],["bundler",{"_index":1805,"title":{},"content":{"120":{}},"tags":{}}],["burn",{"_index":1089,"title":{},"content":{"41":{}},"tags":{}}],["button",{"_index":531,"title":{},"content":{"19":{},"30":{},"79":{},"94":{},"95":{},"96":{},"110":{},"141":{},"142":{}},"tags":{}}],["button\";import",{"_index":1682,"title":{},"content":{"141":{}},"tags":{}}],["c",{"_index":1203,"title":{},"content":{"66":{},"89":{}},"tags":{}}],["cach",{"_index":330,"title":{},"content":{"29":{},"30":{},"72":{},"75":{},"120":{}},"tags":{}}],["calcul",{"_index":1826,"title":{},"content":{"103":{}},"tags":{}}],["call",{"_index":446,"title":{},"content":{"22":{},"23":{},"30":{},"78":{},"80":{},"103":{},"126":{},"127":{},"136":{}},"tags":{}}],["callback",{"_index":1532,"title":{"142":{}},"content":{"80":{},"131":{},"136":{},"142":{}},"tags":{}}],["camera",{"_index":1219,"title":{"96":{}},"content":{"92":{},"93":{},"94":{},"95":{},"96":{},"97":{}},"tags":{}}],["camera\";import",{"_index":1335,"title":{},"content":{"96":{}},"tags":{}}],["camera.getcamerapermissionstatus().then(setcamerapermiss",{"_index":1259,"title":{},"content":{"94":{},"96":{}},"tags":{}}],["camera.requestcamerapermiss",{"_index":1262,"title":{},"content":{"94":{},"96":{}},"tags":{}}],["camerabutton",{"_index":1371,"title":{},"content":{"96":{}},"tags":{}}],["cameracontain",{"_index":1381,"title":{},"content":{"96":{}},"tags":{}}],["camerapermiss",{"_index":1256,"title":{},"content":{"94":{},"96":{}},"tags":{}}],["camerapermissionstatu",{"_index":1248,"title":{},"content":{"94":{},"96":{}},"tags":{}}],["camerapermissiontext",{"_index":1236,"title":{},"content":{"93":{}},"tags":{}}],["can't",{"_index":1107,"title":{},"content":{"56":{},"100":{},"103":{}},"tags":{}}],["card",{"_index":1036,"title":{},"content":{"127":{}},"tags":{}}],["care",{"_index":1056,"title":{},"content":{"40":{}},"tags":{}}],["caret",{"_index":1620,"title":{"135":{}},"content":{},"tags":{}}],["case",{"_index":997,"title":{},"content":{"56":{},"57":{},"89":{},"93":{},"103":{},"126":{},"127":{}},"tags":{}}],["catch",{"_index":920,"title":{},"content":{"41":{},"71":{}},"tags":{}}],["catcherrors={config.catcherror",{"_index":1555,"title":{},"content":{"80":{},"140":{}},"tags":{}}],["caus",{"_index":593,"title":{},"content":{"17":{},"18":{}},"tags":{}}],["caveat",{"_index":1130,"title":{},"content":{"58":{}},"tags":{}}],["cd",{"_index":242,"title":{"26":{}},"content":{"29":{},"31":{},"39":{},"63":{},"93":{},"126":{}},"tags":{}}],["celtic",{"_index":1652,"title":{},"content":{"138":{},"142":{}},"tags":{}}],["center",{"_index":1392,"title":{},"content":{"96":{}},"tags":{}}],["cert",{"_index":438,"title":{},"content":{"30":{}},"tags":{}}],["certain",{"_index":110,"title":{},"content":{"12":{}},"tags":{}}],["certif",{"_index":433,"title":{},"content":{"30":{}},"tags":{}}],["cf",{"_index":509,"title":{},"content":{"30":{}},"tags":{}}],["chang",{"_index":285,"title":{"41":{},"64":{},"65":{},"118":{},"119":{}},"content":{"28":{},"30":{},"41":{},"46":{},"49":{},"50":{},"51":{},"52":{},"58":{},"66":{},"72":{},"80":{},"93":{},"99":{},"109":{},"116":{},"142":{}},"tags":{}}],["channel",{"_index":815,"title":{},"content":{"47":{},"50":{}},"tags":{}}],["channel:cr",{"_index":854,"title":{},"content":{"50":{}},"tags":{}}],["channel:view",{"_index":857,"title":{},"content":{"50":{}},"tags":{}}],["chatti",{"_index":1411,"title":{},"content":{"78":{}},"tags":{}}],["cheatsheet",{"_index":1906,"title":{},"content":{"110":{},"113":{}},"tags":{}}],["check",{"_index":23,"title":{},"content":{"1":{},"10":{},"30":{},"50":{},"51":{},"58":{},"75":{},"78":{},"96":{},"99":{},"105":{},"125":{},"126":{},"128":{},"132":{},"142":{}},"tags":{}}],["checkautomat",{"_index":896,"title":{},"content":{"51":{}},"tags":{}}],["checkforupdateasync",{"_index":899,"title":{},"content":{"51":{}},"tags":{}}],["checkout",{"_index":322,"title":{},"content":{"29":{},"30":{},"58":{},"75":{}},"tags":{}}],["checksum",{"_index":326,"title":{},"content":{"29":{},"30":{},"75":{}},"tags":{}}],["chi",{"_index":1660,"title":{},"content":{"138":{}},"tags":{}}],["children",{"_index":1038,"title":{},"content":{"127":{}},"tags":{}}],["choos",{"_index":268,"title":{},"content":{"28":{},"29":{},"51":{},"75":{},"128":{},"129":{}},"tags":{}}],["ci",{"_index":289,"title":{},"content":{"28":{},"29":{},"30":{}},"tags":{}}],["ci/cd",{"_index":257,"title":{},"content":{},"tags":{"26":{},"74":{}}}],["ci:publish",{"_index":1572,"title":{},"content":{"75":{}},"tags":{}}],["ci:setup",{"_index":447,"title":{},"content":{"30":{}},"tags":{}}],["ci:test",{"_index":343,"title":{},"content":{"29":{},"75":{}},"tags":{}}],["ci@your.domain",{"_index":493,"title":{},"content":{"30":{}},"tags":{}}],["circl",{"_index":428,"title":{},"content":{"30":{},"110":{}},"tags":{}}],["circle_branch",{"_index":498,"title":{},"content":{"30":{}},"tags":{}}],["circleci",{"_index":241,"title":{"26":{},"28":{},"74":{}},"content":{"26":{},"28":{},"29":{},"30":{},"31":{},"75":{},"76":{}},"tags":{}}],["circleci/config.yml",{"_index":282,"title":{},"content":{"28":{}},"tags":{}}],["circleci/node:10.11",{"_index":318,"title":{},"content":{"29":{},"75":{}},"tags":{}}],["class",{"_index":685,"title":{},"content":{"22":{}},"tags":{}}],["cle",{"_index":1661,"title":{},"content":{"138":{}},"tags":{}}],["clean",{"_index":993,"title":{},"content":{"58":{},"66":{},"126":{}},"tags":{}}],["cleanup",{"_index":522,"title":{},"content":{"30":{}},"tags":{}}],["clear",{"_index":597,"title":{},"content":{"17":{},"41":{},"72":{},"78":{},"103":{},"120":{},"126":{}},"tags":{}}],["clearer",{"_index":575,"title":{},"content":{"16":{}},"tags":{}}],["clearstat",{"_index":986,"title":{},"content":{"126":{}},"tags":{}}],["cleartimeout(timeout.curr",{"_index":1857,"title":{},"content":{"103":{}},"tags":{}}],["cli",{"_index":784,"title":{"32":{}},"content":{"34":{},"35":{},"39":{},"44":{},"47":{},"63":{},"75":{},"77":{},"78":{},"84":{},"87":{},"89":{},"95":{},"125":{}},"tags":{}}],["cli@latest",{"_index":1231,"title":{},"content":{"93":{}},"tags":{}}],["cli@next",{"_index":1277,"title":{},"content":{"95":{}},"tags":{}}],["click",{"_index":400,"title":{},"content":{"30":{},"110":{}},"tags":{}}],["client",{"_index":1735,"title":{"89":{}},"content":{"86":{},"89":{}},"tags":{}}],["clone",{"_index":437,"title":{},"content":{"30":{},"58":{}},"tags":{}}],["close",{"_index":866,"title":{},"content":{"41":{},"50":{}},"tags":{}}],["closecamera",{"_index":1385,"title":{},"content":{"96":{}},"tags":{}}],["cloud",{"_index":1044,"title":{},"content":{"128":{}},"tags":{}}],["cng",{"_index":998,"title":{"98":{},"99":{},"100":{}},"content":{"98":{},"99":{},"100":{},"102":{},"126":{}},"tags":{}}],["cocoapod",{"_index":501,"title":{},"content":{"30":{},"84":{}},"tags":{}}],["code",{"_index":284,"title":{"41":{},"95":{},"138":{}},"content":{"28":{},"39":{},"49":{},"52":{},"56":{},"58":{},"78":{},"83":{},"93":{},"95":{},"96":{},"99":{},"100":{},"133":{},"134":{},"137":{}},"tags":{}}],["code.valu",{"_index":1359,"title":{},"content":{"96":{}},"tags":{}}],["codes.every((cod",{"_index":1358,"title":{},"content":{"96":{}},"tags":{}}],["codescann",{"_index":1351,"title":{},"content":{"96":{}},"tags":{}}],["codescanner={codescann",{"_index":1367,"title":{},"content":{"96":{}},"tags":{}}],["codesign",{"_index":423,"title":{},"content":{"30":{}},"tags":{}}],["codesscreen",{"_index":1311,"title":{},"content":{"95":{}},"tags":{}}],["codesscreenprop",{"_index":1309,"title":{},"content":{"95":{}},"tags":{}}],["codestor",{"_index":1278,"title":{},"content":{"95":{},"96":{}},"tags":{}}],["codestore.addcode(code.valu",{"_index":1360,"title":{},"content":{"96":{}},"tags":{}}],["codestore.codes.length",{"_index":1380,"title":{},"content":{"96":{}},"tags":{}}],["codestore.codes.map((cod",{"_index":1318,"title":{},"content":{"95":{}},"tags":{}}],["codestoremodel",{"_index":1289,"title":{},"content":{"95":{}},"tags":{}}],["codestoresnapshotin",{"_index":1297,"title":{},"content":{"95":{}},"tags":{}}],["codestoresnapshotout",{"_index":1296,"title":{},"content":{"95":{}},"tags":{}}],["codetyp",{"_index":1352,"title":{},"content":{"96":{}},"tags":{}}],["collabor",{"_index":431,"title":{},"content":{"30":{}},"tags":{}}],["collect",{"_index":4,"title":{},"content":{"1":{},"2":{}},"tags":{}}],["color",{"_index":1493,"title":{},"content":{"79":{},"120":{},"142":{}},"tags":{}}],["colors.background",{"_index":1510,"title":{},"content":{"79":{}},"tags":{}}],["com.android.talkback/com.google.android.marvin.talkback.talkbackservic",{"_index":1913,"title":{},"content":{"112":{}},"tags":{}}],["com.google.android.marvin.talkback/com.google.android.marvin.talkback.talkbackservic",{"_index":1912,"title":{},"content":{"112":{}},"tags":{}}],["com.maestroapp",{"_index":983,"title":{},"content":{"126":{},"127":{}},"tags":{}}],["combinereduc",{"_index":1513,"title":{},"content":{"80":{}},"tags":{}}],["come",{"_index":466,"title":{},"content":{"30":{},"50":{},"78":{},"93":{}},"tags":{}}],["command",{"_index":336,"title":{},"content":{"29":{},"30":{},"34":{},"58":{},"66":{},"75":{},"89":{},"95":{},"105":{},"125":{},"126":{}},"tags":{}}],["commit",{"_index":283,"title":{},"content":{"28":{},"30":{},"58":{}},"tags":{}}],["commit_version_bump",{"_index":385,"title":{},"content":{"30":{}},"tags":{}}],["common",{"_index":6,"title":{"17":{}},"content":{"1":{},"2":{},"16":{}},"tags":{}}],["commun",{"_index":12,"title":{"5":{}},"content":{"1":{},"4":{},"5":{},"51":{}},"tags":{}}],["companion",{"_index":974,"title":{},"content":{"125":{}},"tags":{}}],["compat",{"_index":872,"title":{},"content":{"50":{},"58":{},"61":{},"101":{},"105":{}},"tags":{}}],["compil",{"_index":1180,"title":{},"content":{"66":{}},"tags":{}}],["compilesdkvers",{"_index":1124,"title":{},"content":{"58":{}},"tags":{}}],["complet",{"_index":116,"title":{},"content":{"12":{},"29":{},"48":{},"51":{},"88":{},"89":{},"93":{},"125":{},"132":{}},"tags":{}}],["compon",{"_index":157,"title":{"32":{},"34":{},"35":{},"120":{},"133":{},"139":{},"141":{}},"content":{"12":{},"18":{},"32":{},"34":{},"35":{},"37":{},"78":{},"79":{},"96":{},"103":{},"120":{},"126":{},"127":{},"131":{},"133":{},"139":{},"140":{},"141":{}},"tags":{}}],["components/selectfield",{"_index":1611,"title":{},"content":{"133":{},"138":{},"142":{}},"tags":{}}],["components/th",{"_index":1786,"title":{},"content":{"116":{}},"tags":{}}],["concis",{"_index":625,"title":{},"content":{"19":{}},"tags":{}}],["conclus",{"_index":1043,"title":{"128":{}},"content":{},"tags":{}}],["config",{"_index":294,"title":{},"content":{"22":{},"24":{},"28":{},"30":{},"66":{},"83":{}},"tags":{}}],["config.api_url",{"_index":691,"title":{},"content":{"22":{}},"tags":{}}],["config.yml",{"_index":281,"title":{},"content":{"28":{},"29":{},"30":{}},"tags":{}}],["configur",{"_index":311,"title":{"24":{},"71":{},"115":{},"118":{},"119":{}},"content":{"22":{},"23":{},"29":{},"30":{},"41":{},"46":{},"47":{},"58":{},"66":{},"71":{},"75":{},"86":{},"87":{},"93":{},"99":{},"100":{},"112":{},"122":{}},"tags":{}}],["configurestor",{"_index":1441,"title":{},"content":{"79":{},"80":{}},"tags":{}}],["confirm",{"_index":856,"title":{},"content":{"50":{}},"tags":{}}],["confus",{"_index":570,"title":{},"content":{"16":{}},"tags":{}}],["connect",{"_index":409,"title":{},"content":{"21":{},"30":{},"78":{}},"tags":{}}],["consequ",{"_index":1876,"title":{},"content":{"105":{}},"tags":{}}],["console.log('scrollprotectedsectionlist.onscrolltoindexfail",{"_index":1845,"title":{},"content":{"103":{}},"tags":{}}],["console.log(process.env.keep_in_mind",{"_index":932,"title":{},"content":{"72":{}},"tags":{}}],["console.log(process.env.my_var",{"_index":930,"title":{},"content":{"72":{}},"tags":{}}],["const",{"_index":148,"title":{},"content":{"12":{},"22":{},"23":{},"41":{},"71":{},"78":{},"79":{},"80":{},"94":{},"95":{},"96":{},"103":{},"133":{},"136":{},"137":{},"138":{},"141":{},"142":{}},"tags":{}}],["constant",{"_index":133,"title":{},"content":{"12":{}},"tags":{}}],["constructor(config",{"_index":695,"title":{},"content":{"22":{}},"tags":{}}],["contain",{"_index":1269,"title":{},"content":{"79":{},"88":{},"94":{},"95":{},"96":{},"100":{},"133":{}},"tags":{}}],["containerinset",{"_index":1499,"title":{},"content":{"79":{}},"tags":{}}],["containerstyl",{"_index":1667,"title":{},"content":{"138":{},"142":{}},"tags":{}}],["containerstyle={props.styl",{"_index":1625,"title":{},"content":{"135":{},"138":{},"141":{},"142":{}},"tags":{}}],["content",{"_index":568,"title":{},"content":{"16":{},"127":{}},"tags":{}}],["contentcontainerstyle={$contain",{"_index":1265,"title":{},"content":{"94":{},"95":{},"96":{}},"tags":{}}],["context",{"_index":1712,"title":{},"content":{"142":{}},"tags":{}}],["context\";import",{"_index":1344,"title":{},"content":{"96":{},"141":{}},"tags":{}}],["continu",{"_index":248,"title":{"29":{},"30":{}},"content":{"10":{},"26":{},"30":{},"66":{},"98":{},"99":{}},"tags":{}}],["contribut",{"_index":80,"title":{},"content":{"5":{}},"tags":{}}],["control",{"_index":563,"title":{},"content":{"16":{},"19":{},"51":{},"112":{}},"tags":{}}],["conveni",{"_index":709,"title":{},"content":{"22":{},"93":{}},"tags":{}}],["convert",{"_index":1054,"title":{},"content":{"39":{},"79":{}},"tags":{}}],["convey",{"_index":585,"title":{},"content":{"16":{}},"tags":{}}],["cookbook",{"_index":2,"title":{"1":{}},"content":{"5":{},"6":{}},"tags":{}}],["copi",{"_index":279,"title":{},"content":{"28":{},"30":{}},"tags":{}}],["core",{"_index":1176,"title":{},"content":{"65":{}},"tags":{}}],["correct",{"_index":1117,"title":{},"content":{"58":{},"79":{},"103":{}},"tags":{}}],["count",{"_index":1501,"title":{},"content":{"79":{}},"tags":{}}],["counter",{"_index":1452,"title":{},"content":{"79":{},"80":{}},"tags":{}}],["counterreduc",{"_index":1449,"title":{},"content":{"79":{},"80":{}},"tags":{}}],["counterslic",{"_index":1450,"title":{},"content":{"79":{},"80":{}},"tags":{}}],["counterslice.act",{"_index":1482,"title":{},"content":{"79":{}},"tags":{}}],["counterslice.reduc",{"_index":1483,"title":{},"content":{"79":{}},"tags":{}}],["counterslice.t",{"_index":1474,"title":{},"content":{"79":{}},"tags":{}}],["counterst",{"_index":1476,"title":{},"content":{"79":{}},"tags":{}}],["coupl",{"_index":744,"title":{},"content":{"23":{},"84":{}},"tags":{}}],["crash",{"_index":621,"title":{},"content":{"18":{},"56":{},"100":{}},"tags":{}}],["creat",{"_index":41,"title":{"14":{},"48":{},"126":{},"133":{}},"content":{"2":{},"10":{},"20":{},"22":{},"29":{},"30":{},"34":{},"35":{},"48":{},"50":{},"58":{},"72":{},"77":{},"78":{},"79":{},"86":{},"93":{},"98":{},"99":{},"125":{},"126":{},"127":{},"131":{},"133":{}},"tags":{}}],["createcodestoredefaultmodel",{"_index":1299,"title":{},"content":{"95":{}},"tags":{}}],["createslic",{"_index":1475,"title":{},"content":{"79":{}},"tags":{}}],["credenti",{"_index":396,"title":{},"content":{"30":{},"126":{}},"tags":{}}],["critic",{"_index":878,"title":{},"content":{"50":{},"124":{}},"tags":{}}],["curl",{"_index":504,"title":{},"content":{"30":{},"125":{}},"tags":{}}],["current",{"_index":235,"title":{},"content":{"12":{},"30":{},"49":{},"79":{},"94":{}},"tags":{}}],["custom",{"_index":580,"title":{"35":{},"51":{},"134":{}},"content":{"16":{},"18":{},"24":{},"32":{},"51":{},"78":{},"80":{},"99":{},"100":{},"112":{},"131":{},"136":{},"141":{}},"tags":{}}],["d",{"_index":910,"title":{},"content":{"70":{},"117":{}},"tags":{}}],["d6965060e03",{"_index":1009,"title":{},"content":{"126":{}},"tags":{}}],["daemon",{"_index":1150,"title":{},"content":{"58":{}},"tags":{}}],["data",{"_index":1473,"title":{},"content":{"79":{}},"tags":{}}],["data...but",{"_index":1435,"title":{},"content":{"78":{}},"tags":{}}],["data={opt",{"_index":1705,"title":{},"content":{"141":{},"142":{}},"tags":{}}],["date",{"_index":63,"title":{"4":{},"7":{},"11":{},"13":{},"20":{},"25":{},"31":{},"37":{},"42":{},"54":{},"59":{},"67":{},"73":{},"76":{},"82":{},"90":{},"97":{},"102":{},"104":{},"106":{},"114":{},"122":{},"130":{},"143":{}},"content":{"4":{}},"tags":{}}],["deal",{"_index":93,"title":{"12":{}},"content":{"58":{}},"tags":{}}],["debug",{"_index":526,"title":{},"content":{"10":{},"30":{}},"tags":{"55":{}}}],["debug/develop",{"_index":1551,"title":{},"content":{"80":{}},"tags":{}}],["decis",{"_index":1872,"title":{},"content":{"105":{}},"tags":{}}],["decor",{"_index":918,"title":{},"content":{"71":{}},"tags":{}}],["decrement",{"_index":1481,"title":{},"content":{"79":{}},"tags":{}}],["deep",{"_index":473,"title":{},"content":{"30":{}},"tags":{}}],["default",{"_index":313,"title":{},"content":{"9":{},"24":{},"29":{},"30":{},"34":{},"50":{},"64":{},"75":{},"77":{},"78":{},"79":{},"80":{},"93":{},"112":{},"126":{},"128":{},"129":{},"136":{}},"tags":{}}],["default_api_config",{"_index":688,"title":{},"content":{"22":{}},"tags":{}}],["defin",{"_index":1470,"title":{},"content":{"79":{}},"tags":{}}],["delay",{"_index":1542,"title":{},"content":{"80":{}},"tags":{}}],["delete/r",{"_index":1158,"title":{},"content":{"58":{}},"tags":{}}],["demo",{"_index":838,"title":{},"content":{"39":{},"49":{},"93":{},"94":{},"96":{},"126":{},"127":{},"133":{},"138":{},"141":{},"142":{}},"tags":{}}],["demopodcastlistscreen.tsx",{"_index":1042,"title":{},"content":{"127":{}},"tags":{}}],["demotabscreenprop",{"_index":1802,"title":{},"content":{"120":{}},"tags":{}}],["deni",{"_index":1263,"title":{},"content":{"94":{},"96":{}},"tags":{}}],["dep",{"_index":221,"title":{},"content":{"12":{}},"tags":{}}],["depend",{"_index":210,"title":{"40":{},"105":{},"117":{}},"content":{"12":{},"17":{},"29":{},"30":{},"40":{},"58":{},"75":{},"78":{},"79":{},"84":{},"89":{},"93":{},"101":{},"105":{},"106":{},"112":{},"116":{},"132":{}},"tags":{"105":{}}}],["deploy",{"_index":351,"title":{"30":{}},"content":{"30":{},"49":{}},"tags":{}}],["deploy_io",{"_index":464,"title":{},"content":{"30":{}},"tags":{}}],["describ",{"_index":955,"title":{},"content":{"35":{},"57":{}},"tags":{}}],["descript",{"_index":1286,"title":{},"content":{"95":{}},"tags":{}}],["design",{"_index":613,"title":{},"content":{"18":{}},"tags":{}}],["desir",{"_index":1746,"title":{},"content":{"88":{}},"tags":{}}],["destinationdir",{"_index":949,"title":{},"content":{"35":{}},"tags":{}}],["detail",{"_index":537,"title":{},"content":{"30":{},"75":{}},"tags":{}}],["detect",{"_index":656,"title":{},"content":{"10":{}},"tags":{}}],["determin",{"_index":134,"title":{},"content":{"12":{}},"tags":{}}],["detox",{"_index":638,"title":{"8":{},"10":{}},"content":{"8":{},"10":{},"11":{},"66":{},"128":{},"129":{}},"tags":{}}],["detox'",{"_index":642,"title":{},"content":{"9":{},"10":{}},"tags":{}}],["detox/config.json",{"_index":1209,"title":{},"content":{"66":{}},"tags":{}}],["dev",{"_index":410,"title":{},"content":{"30":{},"86":{},"89":{}},"tags":{}}],["develop",{"_index":812,"title":{"89":{}},"content":{"47":{},"57":{},"58":{},"83":{},"87":{},"89":{},"99":{},"100":{},"109":{},"126":{}},"tags":{}}],["developmentcli",{"_index":813,"title":{},"content":{"47":{},"87":{}},"tags":{}}],["devfonts",{"_index":195,"title":{},"content":{"12":{}},"tags":{}}],["devic",{"_index":821,"title":{"110":{},"112":{},"113":{}},"content":{"48":{},"89":{},"93":{},"94":{},"96":{},"112":{},"113":{}},"tags":{}}],["device={devic",{"_index":1366,"title":{},"content":{"96":{}},"tags":{}}],["devtools/reactotronconfig.t",{"_index":1405,"title":{},"content":{"78":{}},"tags":{}}],["dial",{"_index":140,"title":{},"content":{"12":{},"110":{}},"tags":{}}],["dialog",{"_index":603,"title":{},"content":{"17":{}},"tags":{}}],["didn't",{"_index":1131,"title":{},"content":{"58":{}},"tags":{}}],["differ",{"_index":906,"title":{},"content":{"52":{},"61":{},"118":{},"119":{},"126":{}},"tags":{}}],["difficult",{"_index":886,"title":{},"content":{"51":{},"124":{}},"tags":{}}],["dir]/build",{"_index":1750,"title":{},"content":{"88":{}},"tags":{}}],["direct",{"_index":209,"title":{},"content":{"12":{},"127":{}},"tags":{}}],["directli",{"_index":17,"title":{},"content":{"1":{},"23":{},"30":{}},"tags":{}}],["directori",{"_index":788,"title":{},"content":{"34":{},"46":{},"58":{},"78":{},"86":{},"88":{},"99":{},"119":{},"126":{},"133":{}},"tags":{}}],["disabl",{"_index":218,"title":{},"content":{"12":{},"112":{},"133":{},"138":{},"141":{},"142":{}},"tags":{}}],["disappearsonindex",{"_index":1696,"title":{},"content":{"141":{},"142":{}},"tags":{}}],["dismissopt",{"_index":1685,"title":{},"content":{"141":{},"142":{}},"tags":{}}],["dispatch",{"_index":1490,"title":{},"content":{"79":{}},"tags":{}}],["dispatch(decr",{"_index":1508,"title":{},"content":{"79":{}},"tags":{}}],["dispatch(incr",{"_index":1506,"title":{},"content":{"79":{}},"tags":{}}],["dispatchfunc",{"_index":1463,"title":{},"content":{"79":{},"80":{}},"tags":{}}],["display",{"_index":1275,"title":{"96":{},"137":{}},"content":{"95":{},"131":{},"136":{},"137":{},"141":{}},"tags":{}}],["distribut",{"_index":674,"title":{"21":{},"23":{}},"content":{"23":{},"25":{},"47":{},"87":{}},"tags":{}}],["distributeauthtoken",{"_index":747,"title":{},"content":{"23":{}},"tags":{}}],["distributeauthtoken(token",{"_index":769,"title":{},"content":{"23":{}},"tags":{}}],["distributeauthtoken(valu",{"_index":739,"title":{},"content":{"23":{}},"tags":{}}],["diy",{"_index":1229,"title":{},"content":{"92":{}},"tags":{}}],["do",{"_index":194,"title":{},"content":{"12":{},"116":{},"136":{}},"tags":{}}],["doc",{"_index":57,"title":{},"content":{"3":{},"29":{},"30":{},"34":{},"41":{},"53":{},"58":{}},"tags":{}}],["docker",{"_index":314,"title":{},"content":{"29":{},"75":{}},"tags":{}}],["document",{"_index":244,"title":{},"content":{"9":{},"10":{},"26":{},"52":{},"93":{},"95":{},"99":{},"109":{},"110":{},"121":{},"128":{}},"tags":{}}],["doesn't",{"_index":68,"title":{},"content":{"4":{},"23":{},"50":{}},"tags":{}}],["don't",{"_index":13,"title":{},"content":{"1":{},"3":{},"29":{},"30":{},"44":{},"58":{},"60":{},"78":{},"84":{},"109":{},"132":{}},"tags":{}}],["done",{"_index":855,"title":{},"content":{"50":{},"126":{},"142":{}},"tags":{}}],["dotenv",{"_index":455,"title":{},"content":{"30":{},"70":{},"71":{}},"tags":{}}],["doubl",{"_index":1896,"title":{},"content":{"110":{},"112":{}},"tags":{}}],["dough",{"_index":1327,"title":{},"content":{"96":{}},"tags":{}}],["down",{"_index":1025,"title":{},"content":{"58":{},"103":{},"110":{},"112":{},"127":{}},"tags":{}}],["downgrad",{"_index":1776,"title":{},"content":{"101":{}},"tags":{}}],["download",{"_index":861,"title":{},"content":{"50":{},"88":{}},"tags":{}}],["drag",{"_index":1755,"title":{},"content":{"89":{},"112":{}},"tags":{}}],["drawer",{"_index":868,"title":{},"content":{"50":{}},"tags":{}}],["drawerallowfontsc",{"_index":188,"title":{},"content":{"12":{}},"tags":{}}],["drawernavigationopt",{"_index":130,"title":{},"content":{"12":{}},"tags":{}}],["drop",{"_index":832,"title":{},"content":{"48":{}},"tags":{}}],["dropdown",{"_index":270,"title":{},"content":{"28":{}},"tags":{}}],["dual",{"_index":750,"title":{},"content":{"23":{}},"tags":{}}],["due",{"_index":831,"title":{},"content":{"48":{},"56":{}},"tags":{}}],["dure",{"_index":418,"title":{},"content":{"30":{}},"tags":{}}],["e.g",{"_index":629,"title":{},"content":{"19":{},"113":{},"136":{}},"tags":{}}],["e2",{"_index":963,"title":{},"content":{"124":{},"128":{},"129":{}},"tags":{}}],["e58f83",{"_index":224,"title":{},"content":{"12":{}},"tags":{}}],["ea",{"_index":774,"title":{"43":{}},"content":{"43":{},"44":{},"46":{},"48":{},"50":{},"53":{},"54":{},"66":{},"84":{},"86":{},"88":{}},"tags":{}}],["each",{"_index":394,"title":{},"content":{"30":{},"34":{},"78":{},"105":{}},"tags":{}}],["ean",{"_index":1354,"title":{},"content":{"96":{}},"tags":{}}],["eas upd",{"_index":781,"title":{},"content":{},"tags":{"43":{}}}],["eas.json",{"_index":800,"title":{},"content":{"46":{},"47":{},"50":{},"87":{}},"tags":{}}],["eas_local_build_artifacts_dir",{"_index":1747,"title":{},"content":{"88":{}},"tags":{}}],["eas_local_build_artifacts_dir=build",{"_index":1748,"title":{},"content":{"88":{}},"tags":{}}],["easer",{"_index":1129,"title":{},"content":{"58":{}},"tags":{}}],["easi",{"_index":809,"title":{},"content":{"47":{},"99":{},"124":{},"128":{}},"tags":{}}],["easier",{"_index":551,"title":{},"content":{"16":{},"93":{}},"tags":{}}],["easiest",{"_index":732,"title":{},"content":{"23":{},"58":{}},"tags":{}}],["easili",{"_index":1222,"title":{},"content":{"92":{}},"tags":{}}],["echo",{"_index":453,"title":{},"content":{"30":{},"75":{}},"tags":{}}],["edit",{"_index":796,"title":{"47":{}},"content":{"46":{},"94":{}},"tags":{}}],["effect",{"_index":641,"title":{},"content":{"8":{}},"tags":{}}],["ej",{"_index":943,"title":{},"content":{"34":{}},"tags":{}}],["element",{"_index":572,"title":{},"content":{"16":{},"17":{},"18":{},"19":{},"112":{},"126":{},"127":{}},"tags":{}}],["email",{"_index":406,"title":{},"content":{"30":{}},"tags":{}}],["empti",{"_index":1023,"title":{},"content":{"127":{}},"tags":{}}],["emul",{"_index":820,"title":{},"content":{"48":{},"89":{}},"tags":{}}],["emulator/devic",{"_index":862,"title":{},"content":{"50":{}},"tags":{}}],["enabl",{"_index":296,"title":{},"content":{"28":{},"112":{},"113":{}},"tags":{}}],["enablecodescann",{"_index":1238,"title":{},"content":{"93":{}},"tags":{}}],["enabled_accessibility_servic",{"_index":1911,"title":{},"content":{"112":{}},"tags":{}}],["enabledismissonclos",{"_index":1693,"title":{},"content":{"141":{},"142":{}},"tags":{}}],["encount",{"_index":474,"title":{},"content":{"30":{}},"tags":{}}],["encrypt",{"_index":1052,"title":{},"content":{"39":{}},"tags":{}}],["end",{"_index":60,"title":{},"content":{"3":{},"8":{},"12":{},"17":{},"22":{},"30":{},"116":{},"124":{}},"tags":{}}],["ensur",{"_index":1472,"title":{},"content":{"79":{}},"tags":{}}],["entir",{"_index":1404,"title":{},"content":{"78":{}},"tags":{}}],["entri",{"_index":393,"title":{},"content":{"30":{},"64":{},"140":{}},"tags":{}}],["env",{"_index":425,"title":{},"content":{"30":{},"71":{},"72":{},"127":{}},"tags":{}}],["env_var",{"_index":462,"title":{},"content":{"30":{}},"tags":{}}],["env_var=\\\"$env_var",{"_index":454,"title":{},"content":{"30":{}},"tags":{}}],["environ",{"_index":401,"title":{"68":{}},"content":{"30":{},"57":{},"72":{},"73":{},"88":{},"127":{}},"tags":{}}],["environment vari",{"_index":909,"title":{},"content":{},"tags":{"68":{}}}],["episod",{"_index":706,"title":{},"content":{"22":{},"127":{}},"tags":{}}],["episode.titl",{"_index":1040,"title":{},"content":{"127":{}},"tags":{}}],["episodesnapshotin",{"_index":707,"title":{},"content":{"22":{}},"tags":{}}],["error",{"_index":417,"title":{},"content":{"10":{},"30":{},"51":{},"58":{},"120":{}},"tags":{}}],["errorboundari",{"_index":1554,"title":{},"content":{"80":{},"140":{}},"tags":{}}],["eslint",{"_index":217,"title":{},"content":{"12":{},"66":{}},"tags":{}}],["essenti",{"_index":1828,"title":{},"content":{"103":{}},"tags":{}}],["etc",{"_index":1627,"title":{},"content":{"89":{},"136":{}},"tags":{}}],["evalu",{"_index":606,"title":{},"content":{"17":{}},"tags":{}}],["even",{"_index":139,"title":{},"content":{"12":{},"19":{},"41":{},"92":{}},"tags":{}}],["evenli",{"_index":1274,"title":{},"content":{"94":{},"96":{}},"tags":{}}],["event",{"_index":1412,"title":{},"content":{"78":{},"133":{},"136":{},"139":{}},"tags":{}}],["everyon",{"_index":1114,"title":{},"content":{"57":{}},"tags":{}}],["everyth",{"_index":959,"title":{},"content":{"36":{},"96":{},"120":{}},"tags":{}}],["exact",{"_index":331,"title":{},"content":{"29":{},"30":{},"75":{},"103":{}},"tags":{}}],["exactli",{"_index":1851,"title":{},"content":{"103":{}},"tags":{}}],["examin",{"_index":1871,"title":{},"content":{"105":{}},"tags":{}}],["exampl",{"_index":263,"title":{},"content":{"10":{},"16":{},"22":{},"23":{},"27":{},"30":{},"49":{},"51":{},"56":{},"71":{},"77":{},"79":{},"88":{},"92":{},"141":{}},"tags":{}}],["exce",{"_index":1777,"title":{},"content":{"101":{}},"tags":{}}],["excel",{"_index":936,"title":{},"content":{"33":{}},"tags":{}}],["exec",{"_index":521,"title":{},"content":{"30":{}},"tags":{}}],["execut",{"_index":999,"title":{},"content":{"79":{},"93":{},"126":{}},"tags":{}}],["exist",{"_index":535,"title":{},"content":{"30":{},"50":{},"51":{},"77":{},"79":{},"80":{},"103":{}},"tags":{}}],["expect",{"_index":458,"title":{},"content":{"30":{},"100":{}},"tags":{}}],["expect(screen.getbytext(\"hello\")).tobetruthi",{"_index":957,"title":{},"content":{"35":{}},"tags":{}}],["experi",{"_index":545,"title":{"14":{}},"content":{"20":{},"51":{}},"tags":{}}],["expert",{"_index":52,"title":{},"content":{"3":{}},"tags":{}}],["explor",{"_index":59,"title":{},"content":{"3":{},"112":{}},"tags":{}}],["expo",{"_index":778,"title":{"60":{},"83":{},"98":{},"99":{},"100":{}},"content":{"43":{},"44":{},"46":{},"50":{},"51":{},"52":{},"53":{},"60":{},"64":{},"65":{},"66":{},"67":{},"71":{},"83":{},"84":{},"86":{},"89":{},"90":{},"93":{},"98":{},"99":{},"100":{},"101":{},"102":{},"126":{},"132":{}},"tags":{"43":{},"60":{},"83":{},"91":{},"98":{}}}],["expo'",{"_index":1169,"title":{},"content":{"64":{},"83":{},"99":{}},"tags":{}}],["expo-dev-cli",{"_index":1731,"title":{},"content":{},"tags":{"83":{}}}],["expo-upd",{"_index":780,"title":{},"content":{},"tags":{"43":{}}}],["expo.plugin",{"_index":1775,"title":{},"content":{"100":{}},"tags":{}}],["expo:start",{"_index":1804,"title":{},"content":{"120":{}},"tags":{}}],["expoconfig",{"_index":924,"title":{},"content":{"71":{}},"tags":{}}],["expogocompatibility.t",{"_index":1784,"title":{},"content":{"101":{}},"tags":{}}],["export",{"_index":163,"title":{},"content":{"12":{},"22":{},"41":{},"78":{},"79":{},"80":{},"94":{},"95":{},"96":{},"103":{},"133":{},"136":{},"138":{},"141":{},"142":{}},"tags":{}}],["export_method",{"_index":379,"title":{},"content":{"30":{}},"tags":{}}],["ext",{"_index":1187,"title":{},"content":{"66":{}},"tags":{}}],["extend",{"_index":44,"title":{},"content":{"3":{},"22":{},"79":{},"94":{},"95":{},"96":{},"131":{},"133":{},"136":{},"138":{},"141":{},"142":{}},"tags":{}}],["extra",{"_index":830,"title":{},"content":{"48":{},"110":{}},"tags":{}}],["extran",{"_index":571,"title":{},"content":{"16":{}},"tags":{}}],["extrem",{"_index":111,"title":{},"content":{"12":{}},"tags":{}}],["face",{"_index":1891,"title":{},"content":{"110":{}},"tags":{}}],["facebook'",{"_index":972,"title":{},"content":{"125":{}},"tags":{}}],["facebook/fb",{"_index":977,"title":{},"content":{"125":{}},"tags":{}}],["factor",{"_index":142,"title":{},"content":{"12":{},"30":{}},"tags":{}}],["fail",{"_index":290,"title":{},"content":{"28":{},"30":{},"41":{},"103":{}},"tags":{}}],["fairli",{"_index":1111,"title":{},"content":{"57":{}},"tags":{}}],["fake",{"_index":766,"title":{},"content":{"23":{}},"tags":{}}],["fallback",{"_index":328,"title":{},"content":{"29":{},"30":{},"75":{},"137":{}},"tags":{}}],["fals",{"_index":817,"title":{},"content":{"41":{},"47":{},"78":{},"93":{},"103":{},"133":{},"138":{},"141":{},"142":{}},"tags":{}}],["familiar",{"_index":1279,"title":{},"content":{"95":{}},"tags":{}}],["far",{"_index":1825,"title":{},"content":{"103":{}},"tags":{}}],["fast",{"_index":1538,"title":{},"content":{"80":{}},"tags":{}}],["fastest",{"_index":1049,"title":{},"content":{"39":{}},"tags":{}}],["fastfil",{"_index":358,"title":{},"content":{"30":{}},"tags":{}}],["fastlan",{"_index":250,"title":{},"content":{"26":{},"30":{},"84":{}},"tags":{}}],["fastlane_apple_application_specific_password",{"_index":415,"title":{},"content":{"30":{}},"tags":{}}],["fastlane_us",{"_index":405,"title":{},"content":{"30":{}},"tags":{}}],["favoreites_text",{"_index":1037,"title":{},"content":{"127":{}},"tags":{}}],["favorit",{"_index":1014,"title":{},"content":{"58":{},"127":{}},"tags":{}}],["favoritenbateamsscreen",{"_index":1612,"title":{},"content":{"133":{},"138":{},"142":{}},"tags":{}}],["favoritepodcast.yaml",{"_index":1015,"title":{},"content":{"127":{}},"tags":{}}],["favorites_text",{"_index":1020,"title":{},"content":{"127":{}},"tags":{}}],["fc",{"_index":1246,"title":{},"content":{"79":{},"94":{},"95":{},"96":{}},"tags":{}}],["fctext",{"_index":161,"title":{},"content":{"12":{}},"tags":{}}],["fontscal",{"_index":154,"title":{},"content":{"12":{}},"tags":{}}],["fontsiz",{"_index":213,"title":{},"content":{"12":{}},"tags":{}}],["footercompon",{"_index":1697,"title":{},"content":{"141":{},"142":{}},"tags":{}}],["forc",{"_index":389,"title":{},"content":{"30":{}},"tags":{}}],["foreground",{"_index":863,"title":{},"content":{"50":{}},"tags":{}}],["forget",{"_index":1419,"title":{},"content":{"78":{}},"tags":{}}],["fork",{"_index":297,"title":{},"content":{"28":{},"58":{}},"tags":{}}],["form",{"_index":630,"title":{},"content":{"19":{}},"tags":{}}],["format",{"_index":611,"title":{},"content":{"18":{},"66":{},"136":{}},"tags":{}}],["formatt",{"_index":1639,"title":{},"content":{"137":{}},"tags":{}}],["former",{"_index":665,"title":{},"content":{"10":{}},"tags":{}}],["formerli",{"_index":870,"title":{},"content":{"50":{}},"tags":{}}],["forward",{"_index":1161,"title":{},"content":{"60":{}},"tags":{}}],["forwardedref",{"_index":1835,"title":{},"content":{"103":{}},"tags":{}}],["forwardref",{"_index":1595,"title":{},"content":{"133":{},"138":{},"141":{},"142":{}},"tags":{}}],["forwardref(funct",{"_index":1603,"title":{},"content":{"133":{},"138":{},"141":{},"142":{}},"tags":{}}],["found",{"_index":333,"title":{},"content":{"29":{},"30":{},"75":{},"105":{}},"tags":{}}],["foundat",{"_index":888,"title":{},"content":{"51":{}},"tags":{}}],["free",{"_index":303,"title":{},"content":{"28":{},"49":{},"84":{},"136":{}},"tags":{}}],["frontmatt",{"_index":944,"title":{},"content":{"34":{}},"tags":{}}],["full",{"_index":1647,"title":{"138":{}},"content":{},"tags":{}}],["function",{"_index":50,"title":{},"content":{"3":{},"23":{},"41":{},"51":{},"77":{},"80":{},"92":{},"94":{},"95":{},"96":{},"100":{},"103":{},"131":{},"133":{},"137":{},"138":{},"141":{},"142":{}},"tags":{}}],["futur",{"_index":1108,"title":{},"content":{"56":{}},"tags":{}}],["g",{"_index":787,"title":{},"content":{"44":{},"75":{},"84":{},"95":{}},"tags":{}}],["galaxi",{"_index":1932,"title":{},"content":{"113":{}},"tags":{}}],["gboard",{"_index":1922,"title":{},"content":{"112":{}},"tags":{}}],["gem",{"_index":512,"title":{},"content":{"30":{}},"tags":{}}],["gener",{"_index":805,"title":{"32":{},"34":{},"35":{}},"content":{"32":{},"34":{},"35":{},"37":{},"47":{},"48":{},"57":{},"78":{},"87":{},"92":{},"95":{},"98":{},"99":{},"105":{}},"tags":{"32":{}}}],["generalapiproblem",{"_index":708,"title":{},"content":{"22":{}},"tags":{}}],["gestur",{"_index":1586,"title":{},"content":{"110":{},"112":{},"132":{}},"tags":{}}],["gesturehandlerrootview",{"_index":1556,"title":{},"content":{"80":{}},"tags":{}}],["get",{"_index":144,"title":{},"content":{"12":{},"48":{},"51":{},"78":{},"103":{}},"tags":{}}],["getdefaultmiddlewar",{"_index":1525,"title":{},"content":{"80":{}},"tags":{}}],["getepisod",{"_index":704,"title":{},"content":{"22":{}},"tags":{}}],["gigant",{"_index":104,"title":{},"content":{"12":{}},"tags":{}}],["git",{"_index":491,"title":{},"content":{"30":{},"58":{},"105":{}},"tags":{}}],["github",{"_index":266,"title":{},"content":{"28":{},"30":{},"58":{},"105":{}},"tags":{}}],["github/circleci",{"_index":434,"title":{},"content":{"30":{}},"tags":{}}],["github_token",{"_index":424,"title":{},"content":{"30":{}},"tags":{}}],["gitignor",{"_index":1136,"title":{},"content":{"58":{}},"tags":{}}],["given",{"_index":1877,"title":{},"content":{"105":{}},"tags":{}}],["global",{"_index":785,"title":{},"content":{"44":{},"84":{}},"tags":{}}],["go",{"_index":298,"title":{"98":{},"99":{},"100":{}},"content":{"17":{},"22":{},"28":{},"30":{},"34":{},"41":{},"49":{},"58":{},"60":{},"84":{},"89":{},"98":{},"99":{},"100":{},"101":{},"102":{},"109":{},"110":{},"112":{},"125":{},"126":{},"127":{}},"tags":{}}],["goal",{"_index":74,"title":{},"content":{"4":{},"52":{}},"tags":{}}],["good",{"_index":544,"title":{"14":{},"17":{}},"content":{"19":{},"20":{},"78":{},"80":{},"84":{},"93":{}},"tags":{}}],["googl",{"_index":1923,"title":{},"content":{"112":{}},"tags":{}}],["gorhom/bottom",{"_index":1584,"title":{},"content":{"132":{},"140":{},"141":{},"142":{}},"tags":{}}],["grab",{"_index":733,"title":{},"content":{"23":{},"79":{}},"tags":{}}],["gradle.properti",{"_index":1126,"title":{},"content":{"58":{}},"tags":{}}],["gradlew",{"_index":1148,"title":{},"content":{"58":{}},"tags":{}}],["grant",{"_index":1266,"title":{},"content":{"94":{},"96":{}},"tags":{}}],["great",{"_index":261,"title":{},"content":{"19":{},"27":{},"128":{}},"tags":{}}],["groom",{"_index":518,"title":{},"content":{"30":{}},"tags":{}}],["ground",{"_index":1090,"title":{},"content":{"41":{}},"tags":{}}],["group",{"_index":562,"title":{},"content":{"16":{}},"tags":{}}],["guess",{"_index":1829,"title":{},"content":{"103":{}},"tags":{}}],["guid",{"_index":256,"title":{"57":{}},"content":{"10":{},"33":{},"43":{},"46":{},"51":{},"57":{},"58":{},"77":{},"83":{},"98":{},"125":{},"131":{},"136":{}},"tags":{"21":{},"26":{},"55":{},"68":{},"74":{},"105":{}}}],["handi",{"_index":189,"title":{},"content":{"12":{},"105":{}},"tags":{}}],["handl",{"_index":1175,"title":{},"content":{"65":{},"99":{},"103":{},"131":{}},"tags":{}}],["handler",{"_index":1587,"title":{},"content":{"132":{},"133":{}},"tags":{}}],["hang",{"_index":654,"title":{},"content":{"10":{}},"tags":{}}],["happen",{"_index":1550,"title":{},"content":{"80":{}},"tags":{}}],["hasn't",{"_index":1807,"title":{"103":{}},"content":{"103":{},"104":{}},"tags":{}}],["haven't",{"_index":971,"title":{},"content":{"93":{},"103":{},"125":{}},"tags":{}}],["hawk",{"_index":1650,"title":{},"content":{"138":{},"142":{}},"tags":{}}],["head",{"_index":554,"title":{},"content":{"16":{},"49":{},"50":{},"95":{}},"tags":{}}],["header",{"_index":559,"title":{},"content":{"16":{},"19":{},"22":{},"23":{},"49":{}},"tags":{}}],["headerbackallowfontsc",{"_index":179,"title":{},"content":{"12":{}},"tags":{}}],["headertitleallowfontsc",{"_index":180,"title":{},"content":{"12":{}},"tags":{}}],["hear",{"_index":87,"title":{},"content":{"6":{},"110":{},"112":{}},"tags":{}}],["height",{"_index":1388,"title":{},"content":{"96":{}},"tags":{}}],["help",{"_index":40,"title":{},"content":{"2":{},"4":{},"30":{},"109":{},"110":{},"116":{},"127":{}},"tags":{}}],["helper",{"_index":1443,"title":{},"content":{"79":{}},"tags":{}}],["helper=\"select",{"_index":1615,"title":{},"content":{"133":{},"138":{},"142":{}},"tags":{}}],["helpers/withsetpropact",{"_index":1285,"title":{},"content":{"95":{}},"tags":{}}],["here",{"_index":312,"title":{},"content":{"10":{},"29":{},"30":{},"32":{},"40":{},"51":{},"57":{},"75":{},"79":{},"93":{},"95":{},"110":{},"119":{},"127":{},"132":{}},"tags":{}}],["here'",{"_index":1491,"title":{},"content":{"79":{}},"tags":{}}],["here(nul",{"_index":1837,"title":{},"content":{"103":{}},"tags":{}}],["react.usest",{"_index":198,"title":{},"content":{"12":{}},"tags":{}}],["react.usestate(fals",{"_index":1348,"title":{},"content":{"96":{}},"tags":{}}],["react.usestate(tru",{"_index":169,"title":{},"content":{"12":{}},"tags":{}}],["react.usestate(nul",{"_index":1686,"title":{},"content":{"141":{},"142":{}},"tags":{}}],["usesafeareainset",{"_index":1341,"title":{},"content":{"96":{},"141":{},"142":{}},"tags":{}}],["usesafeareainsetsstyl",{"_index":1495,"title":{},"content":{"79":{}},"tags":{}}],["usesafeareainsetsstyle([\"top",{"_index":1500,"title":{},"content":{"79":{}},"tags":{}}],["useselector",{"_index":1448,"title":{},"content":{"79":{},"80":{}},"tags":{}}],["usestate(array",{"_index":1713,"title":{},"content":{"142":{}},"tags":{}}],["withsetpropact",{"_index":1284,"title":{},"content":{"95":{}},"tags":{}}],["wizard",{"_index":1656,"title":{},"content":{"138":{},"142":{}},"tags":{}}],["won't",{"_index":634,"title":{},"content":{"19":{},"58":{},"78":{},"127":{}},"tags":{}}],["work",{"_index":69,"title":{"7":{},"11":{},"13":{},"17":{},"20":{},"25":{},"31":{},"37":{},"42":{},"54":{},"59":{},"67":{},"73":{},"76":{},"82":{},"90":{},"97":{},"102":{},"104":{},"106":{},"114":{},"122":{},"130":{},"143":{}},"content":{"4":{},"24":{},"41":{},"57":{},"71":{},"93":{},"112":{},"120":{}},"tags":{}}],["workflow",{"_index":346,"title":{},"content":{"29":{},"30":{},"75":{},"83":{},"92":{},"98":{},"100":{}},"tags":{}}],["workflow=prebuild",{"_index":1232,"title":{},"content":{"93":{}},"tags":{}}],["working_directori",{"_index":319,"title":{},"content":{"29":{},"30":{},"75":{}},"tags":{}}],["workspac",{"_index":374,"title":{},"content":{"30":{}},"tags":{}}],["wrap",{"_index":615,"title":{},"content":{"18":{},"79":{},"133":{}},"tags":{}}],["wrapper",{"_index":1591,"title":{},"content":{"103":{},"133":{}},"tags":{}}],["write",{"_index":259,"title":{},"content":{"10":{},"27":{},"30":{},"34":{},"66":{}},"tags":{}}],["written",{"_index":31,"title":{},"content":{"2":{},"4":{},"92":{}},"tags":{}}],["wrote",{"_index":670,"title":{},"content":{"10":{}},"tags":{}}],["wwdc",{"_index":1883,"title":{},"content":{"109":{}},"tags":{}}],["x",{"_index":1850,"title":{},"content":{"103":{}},"tags":{}}],["x86_64",{"_index":1147,"title":{},"content":{"58":{}},"tags":{}}],["xcarg",{"_index":376,"title":{},"content":{"30":{}},"tags":{}}],["xcode",{"_index":482,"title":{},"content":{"30":{},"109":{}},"tags":{}}],["xcode_project",{"_index":367,"title":{},"content":{"30":{}},"tags":{}}],["xcodeproj",{"_index":386,"title":{},"content":{"30":{}},"tags":{}}],["y",{"_index":426,"title":{},"content":{"30":{},"103":{}},"tags":{}}],["yaml",{"_index":1563,"title":{"74":{},"75":{}},"content":{"76":{}},"tags":{}}],["yarn",{"_index":337,"title":{"105":{}},"content":{"29":{},"30":{},"36":{},"40":{},"41":{},"58":{},"61":{},"65":{},"70":{},"75":{},"78":{},"79":{},"80":{},"86":{},"89":{},"93":{},"105":{},"106":{},"117":{},"120":{},"126":{},"132":{}},"tags":{"105":{}}}],["yarn.lock",{"_index":479,"title":{},"content":{"30":{}},"tags":{}}],["ye",{"_index":792,"title":{},"content":{"39":{},"46":{},"63":{},"77":{},"93":{}},"tags":{}}],["you'll",{"_index":302,"title":{},"content":{"28":{},"30":{},"44":{},"51":{},"58":{},"72":{},"79":{},"84":{},"89":{},"99":{},"109":{},"112":{},"116":{},"125":{},"126":{}},"tags":{}}],["you'r",{"_index":54,"title":{},"content":{"3":{},"16":{},"44":{},"50":{},"79":{},"84":{},"95":{},"112":{},"126":{},"127":{},"132":{}},"tags":{}}],["you'v",{"_index":875,"title":{},"content":{"50":{}},"tags":{}}],["you:tripl",{"_index":1889,"title":{},"content":{"110":{}},"tags":{}}],["your",{"_index":1793,"title":{},"content":{"118":{}},"tags":{}}],["yourproject",{"_index":366,"title":{},"content":{"30":{}},"tags":{}}],["yourproject.log",{"_index":543,"title":{},"content":{"30":{}},"tags":{}}],["yourproject.xcworkspac",{"_index":375,"title":{},"content":{"30":{}},"tags":{}}],["yourself",{"_index":529,"title":{},"content":{"30":{}},"tags":{}}],["zxvf",{"_index":1752,"title":{},"content":{"89":{}},"tags":{}}]],"pipeline":["stemmer"]}} \ No newline at end of file +{"documents":[{"id":142,"pageTitle":"","sectionTitle":"Welcome to the Ignite Cookbook 👋","sectionRoute":"/docs/intro","type":"docs"},{"id":143,"pageTitle":"","sectionTitle":"What is a Recipe?","sectionRoute":"/docs/intro#what-is-a-recipe","type":"docs"},{"id":144,"pageTitle":"","sectionTitle":"Who is this for?","sectionRoute":"/docs/intro#who-is-this-for","type":"docs"},{"id":145,"pageTitle":"","sectionTitle":"Are these recipes tested and up-to-date?","sectionRoute":"/docs/intro#are-these-recipes-tested-and-up-to-date","type":"docs"},{"id":146,"pageTitle":"","sectionTitle":"Backed by the Ignite Team & Community","sectionRoute":"/docs/intro#backed-by-the-ignite-team--community","type":"docs"},{"id":147,"pageTitle":"","sectionTitle":"Have an idea for a recipe?","sectionRoute":"/docs/intro#have-an-idea-for-a-recipe","type":"docs"},{"id":148,"pageTitle":"","sectionTitle":"Is this page still up to date? Did it work for you?","sectionRoute":"/docs/intro","type":"docs"},{"id":1,"pageTitle":"","sectionTitle":"Dealing With Accessibility Font Sizes in React Native","sectionRoute":"/docs/recipes/AccessibilityFontSizes","type":"docs"},{"id":2,"pageTitle":"","sectionTitle":"Is this page still up to date? Did it work for you?","sectionRoute":"/docs/recipes/AccessibilityFontSizes","type":"docs"},{"id":37,"pageTitle":"CircleCI CD Setup - React Native","sectionTitle":"CircleCI CD Setup - React Native","sectionRoute":"/docs/recipes/CircleCIRNSetup","type":"docs"},{"id":38,"pageTitle":"CircleCI CD Setup - React Native","sectionTitle":"First Things First","sectionRoute":"/docs/recipes/CircleCIRNSetup#first-things-first","type":"docs"},{"id":39,"pageTitle":"CircleCI CD Setup - React Native","sectionTitle":"CircleCI Setup","sectionRoute":"/docs/recipes/CircleCIRNSetup#circleci-setup","type":"docs"},{"id":40,"pageTitle":"CircleCI CD Setup - React Native","sectionTitle":"Continuous Integration","sectionRoute":"/docs/recipes/CircleCIRNSetup#continuous-integration","type":"docs"},{"id":41,"pageTitle":"CircleCI CD Setup - React Native","sectionTitle":"iOS Continuous Deployment","sectionRoute":"/docs/recipes/CircleCIRNSetup#ios-continuous-deployment","type":"docs"},{"id":42,"pageTitle":"CircleCI CD Setup - React Native","sectionTitle":"Is this page still up to date? Did it work for you?","sectionRoute":"/docs/recipes/CircleCIRNSetup","type":"docs"},{"id":3,"pageTitle":"Creating a Good Experience for Screen Readers","sectionTitle":"Creating a Good Experience for Screen Readers","sectionRoute":"/docs/recipes/CreatingGreateExperienceForScreenReaders","type":"docs"},{"id":4,"pageTitle":"Creating a Good Experience for Screen Readers","sectionTitle":"UI Patterns","sectionRoute":"/docs/recipes/CreatingGreateExperienceForScreenReaders#ui-patterns","type":"docs"},{"id":5,"pageTitle":"Creating a Good Experience for Screen Readers","sectionTitle":"Screens","sectionRoute":"/docs/recipes/CreatingGreateExperienceForScreenReaders#screens","type":"docs"},{"id":6,"pageTitle":"Creating a Good Experience for Screen Readers","sectionTitle":"Common patterns that require more work to add good UX for screen readers","sectionRoute":"/docs/recipes/CreatingGreateExperienceForScreenReaders#common-patterns-that-require-more-work-to-add-good-ux-for-screen-readers","type":"docs"},{"id":7,"pageTitle":"Creating a Good Experience for Screen Readers","sectionTitle":"RN-specific issues","sectionRoute":"/docs/recipes/CreatingGreateExperienceForScreenReaders#rn-specific-issues","type":"docs"},{"id":8,"pageTitle":"Creating a Good Experience for Screen Readers","sectionTitle":"Labeling","sectionRoute":"/docs/recipes/CreatingGreateExperienceForScreenReaders#labeling","type":"docs"},{"id":9,"pageTitle":"Creating a Good Experience for Screen Readers","sectionTitle":"Is this page still up to date? Did it work for you?","sectionRoute":"/docs/recipes/CreatingGreateExperienceForScreenReaders","type":"docs"},{"id":28,"pageTitle":"Detox Intro","sectionTitle":"Detox Intro","sectionRoute":"/docs/recipes/DetoxIntro","type":"docs"},{"id":29,"pageTitle":"Detox Intro","sectionTitle":"Installation","sectionRoute":"/docs/recipes/DetoxIntro#installation","type":"docs"},{"id":30,"pageTitle":"Detox Intro","sectionTitle":"What's unique about Detox","sectionRoute":"/docs/recipes/DetoxIntro#whats-unique-about-detox","type":"docs"},{"id":31,"pageTitle":"Detox Intro","sectionTitle":"Is this page still up to date? Did it work for you?","sectionRoute":"/docs/recipes/DetoxIntro","type":"docs"},{"id":32,"pageTitle":"","sectionTitle":"Distributing Auth Token to APISauce","sectionRoute":"/docs/recipes/DistributingAuthTokenToAPI","type":"docs"},{"id":33,"pageTitle":"","sectionTitle":"Review of API Instance and Auth Store","sectionRoute":"/docs/recipes/DistributingAuthTokenToAPI#review-of-api-instance-and-auth-store","type":"docs"},{"id":34,"pageTitle":"","sectionTitle":"Distributing Auth Token to API Instance","sectionRoute":"/docs/recipes/DistributingAuthTokenToAPI#distributing-auth-token-to-api-instance","type":"docs"},{"id":35,"pageTitle":"","sectionTitle":"Other configuration","sectionRoute":"/docs/recipes/DistributingAuthTokenToAPI#other-configuration","type":"docs"},{"id":36,"pageTitle":"","sectionTitle":"Is this page still up to date? Did it work for you?","sectionRoute":"/docs/recipes/DistributingAuthTokenToAPI","type":"docs"},{"id":16,"pageTitle":"","sectionTitle":"EAS Update","sectionRoute":"/docs/recipes/EASUpdate","type":"docs"},{"id":17,"pageTitle":"","sectionTitle":"Appetizer","sectionRoute":"/docs/recipes/EASUpdate#appetizer","type":"docs"},{"id":18,"pageTitle":"","sectionTitle":"Steps","sectionRoute":"/docs/recipes/EASUpdate#steps","type":"docs"},{"id":19,"pageTitle":"","sectionTitle":"1. Project Setup","sectionRoute":"/docs/recipes/EASUpdate#1-project-setup","type":"docs"},{"id":20,"pageTitle":"","sectionTitle":"2. Edit Build Profiles","sectionRoute":"/docs/recipes/EASUpdate#2-edit-build-profiles","type":"docs"},{"id":21,"pageTitle":"","sectionTitle":"3. Create the Build","sectionRoute":"/docs/recipes/EASUpdate#3-create-the-build","type":"docs"},{"id":22,"pageTitle":"","sectionTitle":"4. Making a Project Update","sectionRoute":"/docs/recipes/EASUpdate#4-making-a-project-update","type":"docs"},{"id":23,"pageTitle":"","sectionTitle":"5. Publishing OTA","sectionRoute":"/docs/recipes/EASUpdate#5-publishing-ota","type":"docs"},{"id":24,"pageTitle":"","sectionTitle":"Customized Update Flow","sectionRoute":"/docs/recipes/EASUpdate#customized-update-flow","type":"docs"},{"id":25,"pageTitle":"","sectionTitle":"Notes","sectionRoute":"/docs/recipes/EASUpdate#notes","type":"docs"},{"id":26,"pageTitle":"","sectionTitle":"More Resources","sectionRoute":"/docs/recipes/EASUpdate#more-resources","type":"docs"},{"id":27,"pageTitle":"","sectionTitle":"Is this page still up to date? Did it work for you?","sectionRoute":"/docs/recipes/EASUpdate","type":"docs"},{"id":10,"pageTitle":"","sectionTitle":"Environment Variables","sectionRoute":"/docs/recipes/EnvironmentVariables","type":"docs"},{"id":11,"pageTitle":"","sectionTitle":"Setup","sectionRoute":"/docs/recipes/EnvironmentVariables#setup","type":"docs"},{"id":12,"pageTitle":"","sectionTitle":"Install","sectionRoute":"/docs/recipes/EnvironmentVariables#install","type":"docs"},{"id":13,"pageTitle":"","sectionTitle":"Configure","sectionRoute":"/docs/recipes/EnvironmentVariables#configure","type":"docs"},{"id":14,"pageTitle":"","sectionTitle":"Usage","sectionRoute":"/docs/recipes/EnvironmentVariables#usage","type":"docs"},{"id":15,"pageTitle":"","sectionTitle":"Is this page still up to date? Did it work for you?","sectionRoute":"/docs/recipes/EnvironmentVariables","type":"docs"},{"id":124,"pageTitle":"","sectionTitle":"Expo Router","sectionRoute":"/docs/recipes/ExpoRouter","type":"docs"},{"id":125,"pageTitle":"","sectionTitle":"Overview","sectionRoute":"/docs/recipes/ExpoRouter#overview","type":"docs"},{"id":126,"pageTitle":"","sectionTitle":"Installation and Project Configuration","sectionRoute":"/docs/recipes/ExpoRouter#installation-and-project-configuration","type":"docs"},{"id":127,"pageTitle":"","sectionTitle":"Reworking the Directory Structure","sectionRoute":"/docs/recipes/ExpoRouter#reworking-the-directory-structure","type":"docs"},{"id":128,"pageTitle":"","sectionTitle":"Fix Imports","sectionRoute":"/docs/recipes/ExpoRouter#fix-imports","type":"docs"},{"id":129,"pageTitle":"","sectionTitle":"Creating File-based Routes","sectionRoute":"/docs/recipes/ExpoRouter#creating-file-based-routes","type":"docs"},{"id":130,"pageTitle":"","sectionTitle":"src/app/_layout.tsx","sectionRoute":"/docs/recipes/ExpoRouter#srcapp_layouttsx","type":"docs"},{"id":131,"pageTitle":"","sectionTitle":"src/app/(app)/_layout.tsx","sectionRoute":"/docs/recipes/ExpoRouter#srcappapp_layouttsx","type":"docs"},{"id":132,"pageTitle":"","sectionTitle":"src/app/log-in.tsx","sectionRoute":"/docs/recipes/ExpoRouter#srcapplog-intsx","type":"docs"},{"id":133,"pageTitle":"","sectionTitle":"src/app/(app)/index.tsx","sectionRoute":"/docs/recipes/ExpoRouter#srcappappindextsx","type":"docs"},{"id":134,"pageTitle":"","sectionTitle":"Checkpoint","sectionRoute":"/docs/recipes/ExpoRouter#checkpoint","type":"docs"},{"id":135,"pageTitle":"","sectionTitle":"Adding Tab Navigation","sectionRoute":"/docs/recipes/ExpoRouter#adding-tab-navigation","type":"docs"},{"id":136,"pageTitle":"","sectionTitle":"Creating Tab Screens","sectionRoute":"/docs/recipes/ExpoRouter#creating-tab-screens","type":"docs"},{"id":137,"pageTitle":"","sectionTitle":"Showroom Screen","sectionRoute":"/docs/recipes/ExpoRouter#showroom-screen","type":"docs"},{"id":138,"pageTitle":"","sectionTitle":"Code Cleanup","sectionRoute":"/docs/recipes/ExpoRouter#code-cleanup","type":"docs"},{"id":139,"pageTitle":"","sectionTitle":"Summary","sectionRoute":"/docs/recipes/ExpoRouter#summary","type":"docs"},{"id":140,"pageTitle":"","sectionTitle":"Additional Resources","sectionRoute":"/docs/recipes/ExpoRouter#additional-resources","type":"docs"},{"id":141,"pageTitle":"","sectionTitle":"Is this page still up to date? Did it work for you?","sectionRoute":"/docs/recipes/ExpoRouter","type":"docs"},{"id":43,"pageTitle":"","sectionTitle":"Add component tests to npx ignite-cli generate component","sectionRoute":"/docs/recipes/GeneratorComponentTests","type":"docs"},{"id":44,"pageTitle":"","sectionTitle":"Setup @testing-library/react-native","sectionRoute":"/docs/recipes/GeneratorComponentTests#setup-testing-libraryreact-native","type":"docs"},{"id":45,"pageTitle":"","sectionTitle":"Component Generators","sectionRoute":"/docs/recipes/GeneratorComponentTests#component-generators","type":"docs"},{"id":46,"pageTitle":"","sectionTitle":"Customizing Component Generators","sectionRoute":"/docs/recipes/GeneratorComponentTests#customizing-component-generators","type":"docs"},{"id":47,"pageTitle":"","sectionTitle":"Testing","sectionRoute":"/docs/recipes/GeneratorComponentTests#testing","type":"docs"},{"id":48,"pageTitle":"","sectionTitle":"Is this page still up to date? Did it work for you?","sectionRoute":"/docs/recipes/GeneratorComponentTests","type":"docs"},{"id":62,"pageTitle":"","sectionTitle":"Setting Up Maestro in Ignite","sectionRoute":"/docs/recipes/MaestroSetup","type":"docs"},{"id":63,"pageTitle":"","sectionTitle":"Overview","sectionRoute":"/docs/recipes/MaestroSetup#overview","type":"docs"},{"id":64,"pageTitle":"","sectionTitle":"Maestro Installation","sectionRoute":"/docs/recipes/MaestroSetup#maestro-installation","type":"docs"},{"id":65,"pageTitle":"","sectionTitle":"Creating our first Maestro Flow","sectionRoute":"/docs/recipes/MaestroSetup#creating-our-first-maestro-flow","type":"docs"},{"id":66,"pageTitle":"","sectionTitle":"Let's see what else Maestro can do","sectionRoute":"/docs/recipes/MaestroSetup#lets-see-what-else-maestro-can-do","type":"docs"},{"id":67,"pageTitle":"","sectionTitle":"Conclusion","sectionRoute":"/docs/recipes/MaestroSetup#conclusion","type":"docs"},{"id":68,"pageTitle":"","sectionTitle":"Notes","sectionRoute":"/docs/recipes/MaestroSetup#notes","type":"docs"},{"id":69,"pageTitle":"","sectionTitle":"Is this page still up to date? Did it work for you?","sectionRoute":"/docs/recipes/MaestroSetup","type":"docs"},{"id":57,"pageTitle":"","sectionTitle":"Migrating to MMKV","sectionRoute":"/docs/recipes/MigratingToMMKV","type":"docs"},{"id":58,"pageTitle":"","sectionTitle":"Overview","sectionRoute":"/docs/recipes/MigratingToMMKV#overview","type":"docs"},{"id":59,"pageTitle":"","sectionTitle":"Project Dependencies","sectionRoute":"/docs/recipes/MigratingToMMKV#project-dependencies","type":"docs"},{"id":60,"pageTitle":"","sectionTitle":"Code Changes","sectionRoute":"/docs/recipes/MigratingToMMKV#code-changes","type":"docs"},{"id":61,"pageTitle":"","sectionTitle":"Is this page still up to date? Did it work for you?","sectionRoute":"/docs/recipes/MigratingToMMKV","type":"docs"},{"id":70,"pageTitle":"Patching/Building Android .aar From Source","sectionTitle":"Patching/Building Android .aar From Source","sectionRoute":"/docs/recipes/PatchingBuildingAndroid","type":"docs"},{"id":71,"pageTitle":"Patching/Building Android .aar From Source","sectionTitle":"Why?","sectionRoute":"/docs/recipes/PatchingBuildingAndroid#why","type":"docs"},{"id":72,"pageTitle":"Patching/Building Android .aar From Source","sectionTitle":"Official Guides","sectionRoute":"/docs/recipes/PatchingBuildingAndroid#official-guides","type":"docs"},{"id":73,"pageTitle":"Patching/Building Android .aar From Source","sectionTitle":"Steps","sectionRoute":"/docs/recipes/PatchingBuildingAndroid#steps","type":"docs"},{"id":74,"pageTitle":"Patching/Building Android .aar From Source","sectionTitle":"Is this page still up to date? Did it work for you?","sectionRoute":"/docs/recipes/PatchingBuildingAndroid","type":"docs"},{"id":49,"pageTitle":"","sectionTitle":"Pristine Expo Project","sectionRoute":"/docs/recipes/PristineExpoProject","type":"docs"},{"id":50,"pageTitle":"","sectionTitle":"Notes","sectionRoute":"/docs/recipes/PristineExpoProject#notes","type":"docs"},{"id":51,"pageTitle":"","sectionTitle":"Steps","sectionRoute":"/docs/recipes/PristineExpoProject#steps","type":"docs"},{"id":52,"pageTitle":"","sectionTitle":"Project Initialization","sectionRoute":"/docs/recipes/PristineExpoProject#project-initialization","type":"docs"},{"id":53,"pageTitle":"","sectionTitle":"Filesystem Changes","sectionRoute":"/docs/recipes/PristineExpoProject#filesystem-changes","type":"docs"},{"id":54,"pageTitle":"","sectionTitle":"Package Changes","sectionRoute":"/docs/recipes/PristineExpoProject#package-changes","type":"docs"},{"id":55,"pageTitle":"","sectionTitle":"package.json Script Updates","sectionRoute":"/docs/recipes/PristineExpoProject#packagejson-script-updates","type":"docs"},{"id":56,"pageTitle":"","sectionTitle":"Is this page still up to date? Did it work for you?","sectionRoute":"/docs/recipes/PristineExpoProject","type":"docs"},{"id":117,"pageTitle":"","sectionTitle":"VisionCamera","sectionRoute":"/docs/recipes/ReactNativeVisionCamera","type":"docs"},{"id":118,"pageTitle":"","sectionTitle":"Overview","sectionRoute":"/docs/recipes/ReactNativeVisionCamera#overview","type":"docs"},{"id":119,"pageTitle":"","sectionTitle":"Installation","sectionRoute":"/docs/recipes/ReactNativeVisionCamera#installation","type":"docs"},{"id":120,"pageTitle":"","sectionTitle":"Permissions","sectionRoute":"/docs/recipes/ReactNativeVisionCamera#permissions","type":"docs"},{"id":121,"pageTitle":"","sectionTitle":"Codes Store & Screen","sectionRoute":"/docs/recipes/ReactNativeVisionCamera#codes-store--screen","type":"docs"},{"id":122,"pageTitle":"","sectionTitle":"Displaying the Camera","sectionRoute":"/docs/recipes/ReactNativeVisionCamera#displaying-the-camera","type":"docs"},{"id":123,"pageTitle":"","sectionTitle":"Is this page still up to date? Did it work for you?","sectionRoute":"/docs/recipes/ReactNativeVisionCamera","type":"docs"},{"id":78,"pageTitle":"","sectionTitle":"Redux","sectionRoute":"/docs/recipes/Redux","type":"docs"},{"id":79,"pageTitle":"","sectionTitle":"Remove Mobx-State-Tree","sectionRoute":"/docs/recipes/Redux#remove-mobx-state-tree","type":"docs"},{"id":80,"pageTitle":"","sectionTitle":"Add Redux","sectionRoute":"/docs/recipes/Redux#add-redux","type":"docs"},{"id":81,"pageTitle":"","sectionTitle":"Persistence","sectionRoute":"/docs/recipes/Redux#persistence","type":"docs"},{"id":82,"pageTitle":"","sectionTitle":"Reactotron Support","sectionRoute":"/docs/recipes/Redux#reactotron-support","type":"docs"},{"id":83,"pageTitle":"","sectionTitle":"Is this page still up to date? Did it work for you?","sectionRoute":"/docs/recipes/Redux","type":"docs"},{"id":75,"pageTitle":"Sample YAML for CircleCi for Ignite","sectionTitle":"Sample YAML for CircleCi for Ignite","sectionRoute":"/docs/recipes/SampleYAMLCircleCI","type":"docs"},{"id":76,"pageTitle":"Sample YAML for CircleCi for Ignite","sectionTitle":"Sampl YAML File","sectionRoute":"/docs/recipes/SampleYAMLCircleCI#sampl-yaml-file","type":"docs"},{"id":77,"pageTitle":"Sample YAML for CircleCi for Ignite","sectionTitle":"Is this page still up to date? Did it work for you?","sectionRoute":"/docs/recipes/SampleYAMLCircleCI","type":"docs"},{"id":149,"pageTitle":"","sectionTitle":"SelectField using react-native-bottom-sheet","sectionRoute":"/docs/recipes/SelectFieldWithBottomSheet","type":"docs"},{"id":150,"pageTitle":"","sectionTitle":"1. Installation","sectionRoute":"/docs/recipes/SelectFieldWithBottomSheet#1-installation","type":"docs"},{"id":151,"pageTitle":"","sectionTitle":"2. Create the SelectField.tsx Component File","sectionRoute":"/docs/recipes/SelectFieldWithBottomSheet#2-create-the-selectfieldtsx-component-file","type":"docs"},{"id":152,"pageTitle":"","sectionTitle":"3. Add New Props and Customize the TextField","sectionRoute":"/docs/recipes/SelectFieldWithBottomSheet#3-add-new-props-and-customize-the-textfield","type":"docs"},{"id":153,"pageTitle":"","sectionTitle":"Add a Caret Icon Accessory","sectionRoute":"/docs/recipes/SelectFieldWithBottomSheet#add-a-caret-icon-accessory","type":"docs"},{"id":154,"pageTitle":"","sectionTitle":"Add Props","sectionRoute":"/docs/recipes/SelectFieldWithBottomSheet#add-props","type":"docs"},{"id":155,"pageTitle":"","sectionTitle":"Add Logic to Display Selected Options","sectionRoute":"/docs/recipes/SelectFieldWithBottomSheet#add-logic-to-display-selected-options","type":"docs"},{"id":156,"pageTitle":"","sectionTitle":"Full Code For This Step","sectionRoute":"/docs/recipes/SelectFieldWithBottomSheet#full-code-for-this-step","type":"docs"},{"id":157,"pageTitle":"","sectionTitle":"4. Add the Sheet Components","sectionRoute":"/docs/recipes/SelectFieldWithBottomSheet#4-add-the-sheet-components","type":"docs"},{"id":158,"pageTitle":"","sectionTitle":"Add the BottomSheetModalProvider","sectionRoute":"/docs/recipes/SelectFieldWithBottomSheet#add-the-bottomsheetmodalprovider","type":"docs"},{"id":159,"pageTitle":"","sectionTitle":"Add the Necessary Components to SelectField","sectionRoute":"/docs/recipes/SelectFieldWithBottomSheet#add-the-necessary-components-to-selectfield","type":"docs"},{"id":160,"pageTitle":"","sectionTitle":"5. Add Selected State to Options and Hook Up Callback","sectionRoute":"/docs/recipes/SelectFieldWithBottomSheet#5-add-selected-state-to-options-and-hook-up-callback","type":"docs"},{"id":161,"pageTitle":"","sectionTitle":"Is this page still up to date? Did it work for you?","sectionRoute":"/docs/recipes/SelectFieldWithBottomSheet","type":"docs"},{"id":84,"pageTitle":"","sectionTitle":"Staying With Expo","sectionRoute":"/docs/recipes/StayingWithExpo","type":"docs"},{"id":85,"pageTitle":"","sectionTitle":"Appetizer","sectionRoute":"/docs/recipes/StayingWithExpo#appetizer","type":"docs"},{"id":86,"pageTitle":"","sectionTitle":"Steps","sectionRoute":"/docs/recipes/StayingWithExpo#steps","type":"docs"},{"id":87,"pageTitle":"","sectionTitle":"1. Project Setup","sectionRoute":"/docs/recipes/StayingWithExpo#1-project-setup","type":"docs"},{"id":88,"pageTitle":"","sectionTitle":"2. Build Profile","sectionRoute":"/docs/recipes/StayingWithExpo#2-build-profile","type":"docs"},{"id":89,"pageTitle":"","sectionTitle":"3. Run the Build!","sectionRoute":"/docs/recipes/StayingWithExpo#3-run-the-build","type":"docs"},{"id":90,"pageTitle":"","sectionTitle":"4. Run the Development Client","sectionRoute":"/docs/recipes/StayingWithExpo#4-run-the-development-client","type":"docs"},{"id":91,"pageTitle":"","sectionTitle":"Is this page still up to date? Did it work for you?","sectionRoute":"/docs/recipes/StayingWithExpo","type":"docs"},{"id":100,"pageTitle":"","sectionTitle":"Switch a Project Between Expo Go and Expo CNG","sectionRoute":"/docs/recipes/SwitchBetweenExpoGoCNG","type":"docs"},{"id":101,"pageTitle":"","sectionTitle":"Expo Go -> Expo CNG","sectionRoute":"/docs/recipes/SwitchBetweenExpoGoCNG#expo-go---expo-cng","type":"docs"},{"id":102,"pageTitle":"","sectionTitle":"Expo CNG -> Expo Go","sectionRoute":"/docs/recipes/SwitchBetweenExpoGoCNG#expo-cng---expo-go","type":"docs"},{"id":103,"pageTitle":"","sectionTitle":"Steps","sectionRoute":"/docs/recipes/SwitchBetweenExpoGoCNG#steps","type":"docs"},{"id":104,"pageTitle":"","sectionTitle":"Is this page still up to date? Did it work for you?","sectionRoute":"/docs/recipes/SwitchBetweenExpoGoCNG","type":"docs"},{"id":92,"pageTitle":"","sectionTitle":"TypeScript baseUrl Configuration","sectionRoute":"/docs/recipes/TypeScriptBaseURL","type":"docs"},{"id":93,"pageTitle":"","sectionTitle":"Overview","sectionRoute":"/docs/recipes/TypeScriptBaseURL#overview","type":"docs"},{"id":94,"pageTitle":"","sectionTitle":"Project Dependencies","sectionRoute":"/docs/recipes/TypeScriptBaseURL#project-dependencies","type":"docs"},{"id":95,"pageTitle":"","sectionTitle":"TypeScript Configuration Changes","sectionRoute":"/docs/recipes/TypeScriptBaseURL#typescript-configuration-changes","type":"docs"},{"id":96,"pageTitle":"","sectionTitle":"Babel Configuration Changes","sectionRoute":"/docs/recipes/TypeScriptBaseURL#babel-configuration-changes","type":"docs"},{"id":97,"pageTitle":"","sectionTitle":"Taste Test in a Component!","sectionRoute":"/docs/recipes/TypeScriptBaseURL#taste-test-in-a-component","type":"docs"},{"id":98,"pageTitle":"","sectionTitle":"Resources","sectionRoute":"/docs/recipes/TypeScriptBaseURL#resources","type":"docs"},{"id":99,"pageTitle":"","sectionTitle":"Is this page still up to date? Did it work for you?","sectionRoute":"/docs/recipes/TypeScriptBaseURL","type":"docs"},{"id":105,"pageTitle":"Scrolling to a location that hasn't been rendered using FlatList or SectionList","sectionTitle":"Scrolling to a location that hasn't been rendered using FlatList or SectionList","sectionRoute":"/docs/recipes/UnrenderedItemInScrollView","type":"docs"},{"id":106,"pageTitle":"Scrolling to a location that hasn't been rendered using FlatList or SectionList","sectionTitle":"Is this page still up to date? Did it work for you?","sectionRoute":"/docs/recipes/UnrenderedItemInScrollView","type":"docs"},{"id":115,"pageTitle":"Updating Dependencies with Yarn Audit, Outdated and Upgrade","sectionTitle":"Updating Dependencies with Yarn Audit, Outdated and Upgrade","sectionRoute":"/docs/recipes/UpdatingDependencies","type":"docs"},{"id":116,"pageTitle":"Updating Dependencies with Yarn Audit, Outdated and Upgrade","sectionTitle":"Is this page still up to date? Did it work for you?","sectionRoute":"/docs/recipes/UpdatingDependencies","type":"docs"},{"id":107,"pageTitle":"","sectionTitle":"Using Screen Readers","sectionRoute":"/docs/recipes/UsingScreenReaders","type":"docs"},{"id":108,"pageTitle":"","sectionTitle":"iOS","sectionRoute":"/docs/recipes/UsingScreenReaders#ios","type":"docs"},{"id":109,"pageTitle":"","sectionTitle":"On a simulator","sectionRoute":"/docs/recipes/UsingScreenReaders#on-a-simulator","type":"docs"},{"id":110,"pageTitle":"","sectionTitle":"On a device","sectionRoute":"/docs/recipes/UsingScreenReaders#on-a-device","type":"docs"},{"id":111,"pageTitle":"","sectionTitle":"Android","sectionRoute":"/docs/recipes/UsingScreenReaders#android","type":"docs"},{"id":112,"pageTitle":"","sectionTitle":"Devices with TalkBack installed","sectionRoute":"/docs/recipes/UsingScreenReaders#devices-with-talkback-installed","type":"docs"},{"id":113,"pageTitle":"","sectionTitle":"Devices with Voice Assistant and not TalkBack","sectionRoute":"/docs/recipes/UsingScreenReaders#devices-with-voice-assistant-and-not-talkback","type":"docs"},{"id":114,"pageTitle":"","sectionTitle":"Is this page still up to date? Did it work for you?","sectionRoute":"/docs/recipes/UsingScreenReaders","type":"docs"}],"index":{"version":"2.3.9","fields":["title","content","tags"],"fieldVectors":[["title/142",[0,2.836,1,1.028,2,3.381,3,0.798]],["content/142",[1,2.026,4,5.991,5,2.102,6,5.147,7,4.413,8,1.257,9,5.147,10,5.147,11,5.508,12,4.413,13,3.371,14,6.725,15,6.725,16,3.93,17,5.508,18,2.264,19,3.281,20,3.569,21,4.074,22,3.371,23,3.116,24,4.074]],["tags/142",[25,1.892]],["title/143",[5,2.014]],["content/143",[1,1.652,4,5.913,5,2.523,6,5.08,7,4.356,8,1.509,26,2.621,27,2.463,28,5.913,29,6.637,30,1.8,31,5.436,32,4.796,33,4.796,34,6.637,35,3.001,36,4.356,37,2.277,38,5.436,39,4.356,40,3.632,41,2.074,42,5.436]],["tags/143",[]],["title/144",[]],["content/144",[1,2.252,7,3.993,8,1.565,13,3.05,16,3.556,27,2.258,35,2.751,37,2.087,43,6.084,44,3.329,45,3.993,46,2.048,47,1.851,48,2.527,49,3.438,50,2.509,51,2.01,52,6.084,53,5.421,54,4.06,55,3.021,56,4.983,57,3.993,58,2.305,59,5.421,60,3.686]],["tags/144",[]],["title/145",[5,1.29,61,1.444,62,0.812,63,1.596]],["content/145",[1,1.652,5,2.719,12,4.356,31,5.436,40,3.632,62,1.306,63,3.122,64,5.833,65,4.356,66,4.559,67,3.327,68,5.08,69,2.717,70,4.796,71,3.238,72,4.356,73,3.75,74,5.913,75,3.75,76,6.637]],["tags/145",[]],["title/146",[1,0.918,3,0.713,12,2.42,24,2.233,65,2.42]],["content/146",[1,1.78,2,5.854,10,5.471,11,5.854,12,4.691,65,4.691,70,5.164,77,5.854,78,7.148,79,2.947,80,7.148,81,5.164,82,7.148,83,7.148]],["tags/146",[]],["title/147",[5,1.697,84,4.446]],["content/147",[2,5.814,18,2.389,55,2.803,64,5.129,70,5.129,71,3.463,72,4.658,84,5.814,85,6.324,86,7.098,87,5.814,88,4.3,89,5.814,90,3.659,91,1.68]],["tags/147",[]],["title/148",[58,1.396,62,0.725,63,1.426,69,1.241,92,1.218]],["content/148",[5,2.438,25,5.637]],["tags/148",[]],["title/1",[46,0.815,47,0.737,93,2.967,94,1.544,95,2.288,96,2.549]],["content/1",[3,1.918,8,0.303,24,0.983,36,1.065,45,1.065,46,1.511,47,0.359,48,0.536,60,0.983,67,0.813,73,0.917,75,0.917,79,2.052,94,1.715,95,4.894,96,3.809,97,1.623,98,1.623,99,1.446,100,0.7,101,2.775,102,0.602,103,0.655,104,1.623,105,1.534,106,1.765,107,3.927,108,1.446,109,1.446,110,1.623,111,1.623,112,1.065,113,1.623,114,1.242,115,2.146,116,1.698,117,2.003,118,1.715,119,1.623,120,1.623,121,1.623,122,1.623,123,1.623,124,1.926,125,3.015,126,1.623,127,1.623,128,1.623,129,1.623,130,1.623,131,1.623,132,3.012,133,1.446,134,1.446,135,1.446,136,1.623,137,4.977,138,1.32,139,2.146,140,1.446,141,1.446,142,1.446,143,3.298,144,2.542,145,1.623,146,1.623,147,1.114,148,3.232,149,3.702,150,1.623,151,3.702,152,1.623,153,3.427,154,7.836,155,2.428,156,1.329,157,1.905,158,1.329,159,1.623,160,2.804,161,1.623,162,1.623,163,2.246,164,2.804,165,3.185,166,2.095,167,3.61,168,8.21,169,5.446,170,4.852,171,1.623,172,1.674,173,1.623,174,1.623,175,1.446,176,1.741,177,1.623,178,2.804,179,1.623,180,3.702,181,1.623,182,2.804,183,2.804,184,1.623,185,2.804,186,1.623,187,2.804,188,1.623,189,1.446,190,2.296,191,1.329,192,1.623,193,1.329,194,1.242,195,1.623,196,3.702,197,1.623,198,1.623,199,1.623,200,1.114,201,1.623,202,1.623,203,1.623,204,1.623,205,1.623,206,1.623,207,1.623,208,1.446,209,1.446,210,0.655,211,1.329,212,1.242,213,1.242,214,1.623,215,1.623,216,1.623,217,1.329,218,1.114,219,1.242,220,1.623,221,1.623,222,1.242,223,1.065,224,1.623,225,1.242,226,2.296,227,1.623,228,1.329,229,1.172,230,1.446,231,1.623,232,1.623,233,1.623,234,3.185,235,1.172,236,1.623,237,1.623,238,1.623,239,1.022]],["tags/1",[94,1.213]],["title/2",[58,1.396,62,0.725,63,1.426,69,1.241,92,1.218]],["content/2",[5,2.402,95,5.278,96,5.882,240,7.685]],["tags/2",[]],["title/37",[46,0.902,47,0.816,241,2.155,242,2.321,243,1.752]],["content/37",[26,2.709,37,2.354,38,5.619,61,2.399,62,1.349,138,2.447,241,4.009,244,3.536,245,4.502,246,4.319,247,6.745,248,4.319,249,5.619,250,5.619,251,6.112,252,4.319,253,6.86,254,4.712,255,4.502]],["tags/37",[256,0.692,257,1.397]],["title/38",[112,3.078,258,3.421]],["content/38",[10,5.322,11,5.695,30,1.886,46,1.702,47,1.538,48,2.297,61,3.105,62,1.368,138,2.48,259,5.702,260,4.212,261,5.322,262,3.392,263,3.392,264,6.954]],["tags/38",[]],["title/39",[241,3.172,243,2.58]],["content/39",[3,1.235,22,2.318,26,1.827,30,2.319,35,2.092,37,2.934,62,1.256,71,3.567,79,1.907,91,1.094,102,1.717,106,2.912,124,3.177,138,3.126,176,1.827,241,2.703,254,4.385,255,4.19,258,2.455,265,3.035,266,4.613,267,3.342,268,5.021,269,4.121,270,4.625,271,4.385,272,3.342,273,3.177,274,2.802,275,5.229,276,3.177,277,4.121,278,4.625,279,3.54,280,3.342,281,3.788,282,4.625,283,3.788,284,1.907,285,1.827,286,3.788,287,3.788,288,3.177,289,3.788,290,3.54,291,2.912,292,4.121,293,1.683,294,3.177,295,2.531,296,4.886,297,5.688,298,2.369,299,6.384,300,4.613,301,4.798,302,2.198,303,3.342]],["tags/39",[]],["title/40",[248,3.417,249,4.446]],["content/40",[3,1.817,8,1.171,13,1.761,19,2.556,22,1.761,26,2.474,30,0.953,41,1.637,49,1.985,51,1.16,57,2.305,61,2.599,79,1.448,100,1.515,102,1.304,116,3.174,210,3.143,241,2.053,242,2.211,243,2.978,260,2.128,262,1.714,268,2.413,273,2.413,281,4.291,289,2.877,304,4.291,305,1.922,306,3.943,307,1.944,308,2.211,309,2.413,310,2.877,311,2.069,312,2.209,313,2.743,314,3.13,315,3.325,316,6.178,317,2.538,318,3.13,319,2.877,320,2.96,321,4.291,322,4.01,323,4.291,324,3.661,325,6.085,326,5.131,327,3.943,328,4.01,329,3.785,330,3.785,331,3.785,332,4.01,333,4.01,334,2.429,335,1.944,336,3.686,337,2.069,338,2.877,339,2.413,340,2.538,341,1.985,342,2.689,343,4.667,344,3.13,345,3.661,346,2.305,347,2.877,348,2.305,349,1.761]],["tags/40",[]],["title/41",[248,2.953,350,1.892,351,3.841]],["content/41",[3,1.751,8,0.407,13,1.092,17,0.998,22,2.302,23,0.565,26,1.167,27,0.809,30,1.353,36,0.8,37,1.829,39,0.8,40,0.667,41,0.681,46,0.533,47,0.482,48,1.366,49,0.688,51,1.517,55,1.421,57,1.43,60,1.32,61,0.762,62,0.24,65,1.43,66,0.837,67,0.611,72,0.8,79,0.502,91,1.504,94,1.37,99,1.086,100,0.526,101,2.603,102,1.851,105,0.667,106,0.767,115,0.933,118,0.565,138,2.105,142,1.086,166,0.579,167,0.998,191,0.998,210,1.668,219,0.933,235,0.88,241,3.588,243,2.534,246,0.767,248,0.767,250,5.029,251,3.205,254,2.471,259,0.837,262,1.063,263,1.755,265,1.94,266,1.574,267,0.88,273,3.155,275,1.785,279,0.933,281,2.946,283,1.785,285,0.481,286,1.785,287,0.998,289,3.387,290,0.933,294,1.497,298,1.097,302,0.579,306,3.567,307,1.097,309,1.497,311,0.861,312,0.514,313,0.481,315,2.438,316,3.165,319,2.946,320,1.67,321,2.946,322,2.262,323,1.785,324,3.116,325,3.387,326,2.946,327,1.569,328,0.933,329,2.136,330,0.88,331,0.88,332,2.262,333,0.933,334,2.505,335,1.705,336,3.729,337,0.861,338,1.785,339,0.837,340,2.136,341,1.67,342,0.933,345,2.102,346,0.8,347,0.998,348,1.43,349,1.482,350,1.853,351,2.421,352,0.8,353,1.574,354,1.941,355,1.785,356,0.88,357,0.998,358,1.218,359,1.218,360,1.218,361,2.179,362,1.94,363,2.956,364,2.262,365,1.218,366,1.218,367,2.956,368,1.218,369,1.218,370,1.218,371,1.218,372,1.218,373,1.086,374,1.218,375,1.218,376,1.218,377,1.218,378,1.218,379,1.218,380,1.063,381,0.998,382,1.218,383,1.218,384,1.063,385,1.218,386,1.218,387,0.88,388,1.218,389,1.218,390,1.941,391,0.933,392,1.218,393,0.88,394,0.837,395,2.634,396,0.998,397,1.218,398,0.388,399,1.668,400,1.941,401,1.94,402,3.155,403,2.179,404,2.634,405,1.218,406,1.218,407,1.086,408,1.218,409,0.998,410,1.785,411,2.179,412,0.667,413,1.37,414,0.738,415,1.218,416,1.086,417,2.603,418,1.218,419,1.218,420,1.086,421,1.275,422,1.497,423,1.218,424,2.179,425,3.165,426,1.086,427,1.218,428,1.941,429,1.218,430,0.738,431,1.218,432,1.941,433,1.218,434,2.179,435,4.136,436,1.218,437,1.086,438,1.218,439,0.998,440,2.179,441,1.086,442,2.179,443,0.837,444,1.941,445,0.933,446,0.712,447,3.597,448,1.785,449,1.086,450,1.218,451,0.667,452,0.933,453,1.086,454,1.218,455,0.998,456,1.218,457,1.218,458,0.88,459,1.086,460,1.218,461,2.179,462,1.218,463,4.989,464,2.956,465,1.086,466,0.88,467,1.218,468,1.218,469,1.218,470,1.086,471,1.086,472,2.179,473,0.998,474,1.218,475,0.998,476,1.218,477,1.218,478,1.218,479,1.218,480,1.218,481,1.218,482,1.086,483,1.218,484,1.218,485,1.785,486,1.218,487,0.8,488,1.218,489,1.218,490,1.218,491,5.636,492,1.218,493,1.218,494,1.218,495,2.179,496,2.136,497,0.998,498,1.218,499,1.941,500,1.218,501,3.205,502,0.998,503,1.086,504,1.086,505,1.218,506,1.218,507,1.218,508,1.086,509,1.218,510,1.086,511,1.218,512,2.179,513,3.387,514,2.179,515,1.941,516,1.218,517,2.179,518,1.218,519,3.597,520,1.941,521,1.086,522,0.998,523,1.218,524,0.998,525,1.086,526,0.837,527,1.941,528,1.218,529,1.218,530,1.218,531,0.667,532,1.218,533,1.218,534,1.218,535,0.712,536,1.218,537,1.086,538,1.218,539,1.218,540,1.785,541,1.218,542,1.218,543,1.218]],["tags/41",[]],["title/42",[58,1.396,62,0.725,63,1.426,69,1.241,92,1.218]],["content/42",[5,2.366,46,1.853,47,1.675,241,4.425,242,4.766,243,3.599]],["tags/42",[]],["title/3",[41,1.152,398,1.174,544,2.321,545,2.664,546,2.233]],["content/3",[]],["tags/3",[94,0.519,103,0.452,350,0.452]],["title/4",[7,3.562,547,3.288]],["content/4",[]],["tags/4",[]],["title/5",[398,2.051]],["content/5",[6,3.622,8,1.213,33,3.419,46,1.158,47,1.047,48,1.563,54,2.512,62,0.931,94,2.193,102,2.407,106,2.979,108,4.216,109,4.216,112,3.106,135,4.216,263,3.164,301,4.856,398,2.533,452,3.622,546,2.867,548,4.964,549,6.485,550,3.622,551,6.592,552,3.622,553,3.419,554,4.482,555,6.485,556,4.732,557,3.876,558,2.766,559,3.419,560,4.732,561,3.106,562,5.663,563,6.092,564,4.732,565,4.732,566,4.216,567,5.312,568,3.622,569,4.732,570,4.732,571,4.732,572,4.856,573,5.312,574,4.732,575,4.732,576,3.876,577,2.372,578,4.732,579,3.876,580,2.249,581,2.979,582,4.216,583,3.622,584,2.512,585,4.732,586,2.979,587,4.732,588,2.674,589,3.25,590,3.622]],["tags/5",[]],["title/6",[6,1.839,7,1.577,69,0.809,91,0.568,348,1.577,398,0.765,421,1.036,544,1.512,546,1.455,591,1.968]],["content/6",[8,1.151,10,5.899,42,5.043,51,2.034,60,4.669,172,2.784,210,2.484,298,2.285,320,3.479,352,4.041,398,1.96,470,5.486,520,6.867,546,3.73,572,5.058,592,4.852,593,5.486,594,5.043,595,4.041,596,5.486,597,3.876,598,5.043,599,7.708,600,6.158,601,6.158,602,6.158,603,6.158,604,6.158,605,4.713,606,6.158,607,3.369]],["tags/6",[]],["title/7",[72,3.078,608,4.178,609,3.389]],["content/7",[45,3.878,51,1.952,61,2.067,71,2.883,91,1.398,94,2.738,100,2.549,115,4.522,118,2.738,132,4.375,157,2.067,350,2.384,354,5.264,355,4.839,398,1.881,546,3.579,558,3.453,572,3.878,580,3.569,588,4.243,593,5.264,605,4.522,610,7.51,611,4.522,612,5.264,613,5.909,614,3.72,615,4.058,616,5.909,617,6.69,618,5.909,619,3.878,620,4.269,621,4.839,622,5.264,623,4.839]],["tags/7",[]],["title/8",[624,4.056]],["content/8",[8,1.379,94,3.417,102,2.737,105,4.035,139,4.395,176,2.912,261,4.395,262,2.802,272,4.149,349,2.878,355,4.703,398,2.347,430,3.479,531,3.142,544,3.615,546,3.479,550,4.395,559,4.149,563,4.395,572,3.769,586,3.615,588,4.602,598,4.703,624,5.411,625,5.743,626,6.57,627,5.116,628,4.149,629,4.703,630,4.703,631,4.703,632,5.743,633,5.743,634,4.395,635,4.703,636,5.743,637,5.743]],["tags/8",[]],["title/9",[58,1.396,62,0.725,63,1.426,69,1.241,92,1.218]],["content/9",[5,2.366,41,2.366,398,2.41,544,4.766,545,5.47,546,4.587]],["tags/9",[]],["title/28",[25,3.922,638,3.417]],["content/28",[8,1.337,46,1.75,47,1.581,48,2.361,60,5.112,61,2.5,577,3.583,607,3.911,638,5.313,639,7.148,640,6.368,641,7.148]],["tags/28",[25,1.133,61,0.548]],["title/29",[335,2.391]],["content/29",[1,1.871,73,4.246,244,3.874,313,2.968,335,2.789,362,4.932,642,6.696]],["tags/29",[]],["title/30",[550,3.59,638,2.953,643,4.69]],["content/30",[23,2.311,26,1.969,41,1.558,46,1.22,47,1.103,48,2.22,55,1.969,61,2.97,65,3.272,67,2.499,72,3.272,102,1.851,244,2.57,248,3.139,256,2.202,259,3.425,262,3.278,263,2.433,291,3.139,295,2.728,312,2.102,324,2.914,349,2.499,362,3.272,417,3.139,421,2.151,422,3.425,525,4.442,526,3.425,550,3.816,552,3.816,638,5.506,642,4.442,644,5.987,645,4.084,646,3.464,647,3.816,648,3.021,649,4.442,650,4.986,651,4.986,652,4.084,653,4.986,654,4.986,655,4.986,656,4.986,657,4.986,658,4.986,659,4.986,660,4.986,661,4.442,662,4.986,663,4.986,664,4.986,665,4.986,666,4.986,667,4.986,668,4.442,669,4.986,670,4.986,671,4.442,672,4.986,673,4.084]],["tags/30",[]],["title/31",[58,1.396,62,0.725,63,1.426,69,1.241,92,1.218]],["content/31",[5,2.42,25,5.595,638,4.875]],["tags/31",[]],["title/32",[414,2.501,674,2.836,675,2.836,676,2.836]],["content/32",[1,1.731,5,2.173,16,4.064,37,2.386,102,2.581,245,4.563,255,4.563,380,3.392,409,5.695,646,3.584,676,4.776,677,3.305,678,4.377,679,4.691,680,4.563,681,4.377,682,6.954]],["tags/32",[256,0.494,676,0.769,679,0.632]],["title/33",[64,2.664,380,1.799,414,2.233,680,2.42,681,2.321]],["content/33",[3,1.892,8,0.664,16,2.074,35,1.605,41,1.109,44,2.889,51,1.172,55,1.402,60,2.15,64,2.564,88,2.15,117,1.218,138,1.266,148,2.438,155,1.732,163,3.34,166,1.687,263,2.576,292,3.162,293,1.291,294,3.626,295,1.942,298,1.317,307,1.959,311,1.402,380,2.576,414,3.198,446,2.074,553,2.564,559,2.564,584,2.802,646,1.83,652,2.907,675,2.438,676,3.626,677,1.687,678,2.234,679,2.005,680,4.897,681,5.239,683,1.567,684,3.549,685,6.304,686,6.304,687,3.162,688,5.28,689,6.304,690,2.907,691,3.549,692,4.041,693,3.549,694,3.549,695,3.549,696,3.549,697,3.549,698,2.438,699,3.549,700,3.549,701,3.162,702,3.549,703,2.564,704,3.549,705,3.162,706,2.907,707,3.549,708,3.549,709,3.162,710,3.549,711,2.005,712,3.549,713,3.162,714,2.889,715,6.304,716,3.549,717,3.162,718,3.549,719,2.907,720,3.549,721,3.162,722,3.162,723,2.005,724,3.162,725,2.438,726,3.162,727,3.549,728,3.162]],["tags/33",[]],["title/34",[414,2.233,674,2.532,675,2.532,680,2.42,681,2.321]],["content/34",[3,1.858,8,0.607,17,2.658,18,1.092,27,1.204,50,2.035,51,1.63,55,1.282,56,2.658,68,2.484,91,1.168,100,2.129,102,1.204,105,1.776,117,1.693,138,1.76,148,2.309,153,1.368,166,2.839,172,1.467,255,3.919,263,1.583,291,2.043,293,2.428,311,1.282,348,2.13,349,1.627,362,3.239,380,1.583,414,3.618,446,4.419,487,3.919,559,3.566,583,2.484,586,2.043,631,2.658,674,3.39,675,5.698,676,2.229,679,4.056,681,4.201,711,4.272,717,2.891,719,2.658,721,2.891,722,2.891,723,2.788,724,4.397,725,3.39,729,2.229,730,6.736,731,2.891,732,2.891,733,4.397,734,3.245,735,3.245,736,2.891,737,3.245,738,2.043,739,3.245,740,3.245,741,2.345,742,3.245,743,3.245,744,2.891,745,2.891,746,1.833,747,7.179,748,2.13,749,4.936,750,3.245,751,3.245,752,3.245,753,2.891,754,3.239,755,2.13,756,4.397,757,4.397,758,2.891,759,2.891,760,2.229,761,2.891,762,2.658,763,2.891,764,2.891,765,2.891,766,2.891,767,3.245,768,3.245,769,3.245,770,1.338,771,3.245,772,2.891]],["tags/34",[]],["title/35",[311,2.544]],["content/35",[19,3.487,69,2.406,293,2.6,294,4.909,313,2.823,580,3.397,635,5.854,676,4.909,680,4.691,681,5.313,746,4.038,773,6.459]],["tags/35",[]],["title/36",[58,1.396,62,0.725,63,1.426,69,1.241,92,1.218]],["content/36",[5,2.384,414,4.621,674,5.239,675,5.239,681,4.802]],["tags/36",[]],["title/16",[293,1.975,774,2.97]],["content/16",[1,1.78,20,3.794,30,1.939,62,1.406,138,2.549,256,3.156,293,3.07,774,3.911,775,5.854,776,6.368,777,5.471,778,1.72,779,4.5]],["tags/16",[778,0.269,780,1.119,781,1.119]],["title/17",[782,5.74]],["content/17",[5,2.035,13,3.263,22,3.263,27,2.416,30,2.164,35,2.944,51,2.151,54,3.455,102,2.416,258,3.455,260,3.944,267,4.704,302,3.094,335,2.961,349,3.263,774,4.365,778,2.076,783,4.983,784,3.999,785,5.8,786,4.273,787,4.704]],["tags/17",[]],["title/18",[26,2.544]],["content/18",[]],["tags/18",[]],["title/19",[30,1.272,172,2.121,243,2.229]],["content/19",[8,1.056,18,1.901,19,2.755,27,2.096,30,2.192,55,2.23,62,1.111,91,1.336,102,2.096,103,2.278,138,2.014,256,2.493,285,2.23,293,2.654,307,2.708,311,3.191,324,3.3,334,1.975,335,2.096,413,2.617,421,2.436,583,4.322,746,3.191,770,2.329,774,4.673,778,1.756,779,3.555,788,2.755,789,2.831,790,5.031,791,5.647,792,3.879,793,4.625,794,4.322,795,5.647,796,4.322,797,4.593,798,5.031,799,4.08,800,4.322,801,5.647]],["tags/19",[]],["title/20",[37,1.416,320,2.332,796,3.16,802,2.413]],["content/20",[3,1.897,8,1.304,18,1.774,37,2.853,48,1.741,61,1.843,75,2.977,92,1.741,103,3.152,112,3.458,311,2.081,315,2.796,350,2.126,384,2.571,513,4.316,674,3.619,784,2.641,800,4.033,802,3.079,803,3.317,804,4.316,805,2.442,806,4.919,807,6.972,808,5.71,809,4.033,810,5.98,811,5.269,812,2.796,813,4.694,814,4.316,815,4.694,816,2.977,817,2.977,818,4.694]],["tags/20",[]],["title/21",[37,1.609,41,1.466,819,3.078]],["content/21",[3,1.515,8,0.99,18,1.783,19,2.584,21,4.745,37,2.688,41,1.655,55,2.091,61,1.852,62,1.042,91,1.253,103,3.362,105,2.898,116,3.208,144,3.638,226,4.338,267,3.827,295,2.898,701,4.719,729,3.638,760,3.638,774,4.869,793,4.338,802,4.088,805,2.454,806,4.404,820,5.73,821,4.088,822,3.828,823,5.246,824,5.73,825,5.296,826,6.232,827,5.296,828,4.719,829,5.296,830,4.338,831,4.719,832,4.719,833,4.719]],["tags/21",[]],["title/22",[30,1.12,102,1.532,293,1.502,834,2.836]],["content/22",[1,1.383,3,1.396,62,1.093,70,4.014,71,2.71,102,2.679,132,4.141,211,4.55,235,4.014,263,2.71,284,2.291,285,2.85,293,2.021,298,2.679,303,4.014,334,1.943,351,4.55,353,5.215,554,4.372,559,5.215,683,3.187,753,4.949,770,2.291,777,4.252,835,3.816,836,5.555,837,5.555,838,2.71,839,4.949,840,4.949,841,4.55,842,6.431,843,4.949,844,5.215,845,6.431,846,5.555,847,3.04,848,3.139,849,4.252,850,4.949,851,4.949]],["tags/22",[]],["title/23",[229,3.389,777,3.59,852,3.841]],["content/23",[0,2.67,18,1.308,20,2.995,21,2.355,23,1.801,26,1.535,36,2.551,37,1.334,41,1.215,48,2.754,54,2.063,55,2.229,62,0.765,64,2.808,67,3.331,68,2.975,70,2.808,90,2.003,92,1.284,124,2.67,138,1.386,193,3.183,252,2.447,285,2.624,293,3.325,295,2.127,306,2.063,313,1.535,332,2.975,353,4.078,356,2.808,380,1.896,390,3.463,391,2.975,398,1.796,413,1.801,420,3.463,466,2.808,487,2.551,496,2.808,535,2.271,554,2.355,583,2.975,619,2.551,729,2.67,760,2.67,770,3.007,774,4.238,776,3.463,777,2.975,778,1.358,800,2.975,802,2.271,806,4.183,815,7.197,822,3.088,834,2.67,841,3.183,852,4.623,853,2.975,854,3.887,855,2.975,856,3.887,857,3.887,858,2.975,859,2.447,860,3.887,861,5.028,862,3.887,863,3.887,864,2.975,865,3.463,866,5.028,867,5.644,868,3.463,869,2.551,870,3.887,871,3.887,872,2.808,873,2.975,874,3.887,875,3.887,876,3.887,877,2.975,878,3.463,879,3.463,880,2.551,881,3.887]],["tags/23",[]],["title/24",[293,1.706,580,2.229,869,3.078]],["content/24",[3,1.745,12,4.125,20,2.401,21,2.74,23,3.348,26,1.786,27,1.679,37,1.552,48,2.076,49,2.555,50,1.865,75,2.555,90,2.331,91,1.07,101,4.915,102,1.679,105,2.475,116,2.74,144,3.107,229,3.268,252,2.847,255,2.968,256,1.997,263,2.207,268,3.107,285,1.786,293,3.169,302,2.988,312,1.907,349,3.151,391,3.462,413,2.096,417,2.847,421,2.711,535,2.643,545,3.268,547,2.74,563,3.462,577,2.267,580,2.15,614,2.847,635,3.705,648,2.74,649,4.03,652,5.148,778,1.089,797,2.847,841,3.705,858,3.462,869,4.125,882,4.523,883,4.523,884,4.523,885,4.523,886,4.03,887,4.523,888,4.523,889,3.705,890,4.03,891,4.03,892,4.523,893,4.03,894,4.03,895,5.148,896,4.523,897,4.523,898,2.74,899,4.523,900,4.523,901,4.523]],["tags/24",[]],["title/25",[413,2.986]],["content/25",[22,3.438,47,1.518,49,3.876,74,6.112,102,2.546,244,3.536,284,2.829,285,3.252,295,3.754,309,4.712,315,3.641,430,4.156,778,1.651,797,4.319,902,4.712,903,5.619,904,6.86,905,6.86,906,4.712]],["tags/25",[]],["title/26",[421,2.341,590,4.155]],["content/26",[8,1.327,37,2.884,57,4.658,293,3.257,334,2.483,607,3.884,774,4.899,778,1.708,907,6.324,908,7.098]],["tags/26",[]],["title/27",[58,1.396,62,0.725,63,1.426,69,1.241,92,1.218]],["content/27",[5,2.42,293,2.817,774,4.237]],["tags/27",[]],["title/10",[401,3.562,402,3.728]],["content/10",[]],["tags/10",[256,0.692,909,1.568]],["title/11",[243,3.062]],["content/11",[]],["tags/11",[]],["title/12",[335,2.391]],["content/12",[91,1.765,337,2.946,455,7.088,910,6.647,911,5.124,912,4.215,913,6.647]],["tags/12",[]],["title/13",[311,2.544]],["content/13",[3,1.881,46,1.748,47,1.58,48,1.806,69,1.84,91,1.293,100,2.358,148,2.762,263,2.667,311,2.159,384,2.667,413,3.31,425,4.184,455,5.85,778,1.315,810,4.184,911,3.754,912,4.495,913,6.363,914,6.363,915,5.466,916,7.142,917,7.142,918,5.466,919,5.466,920,4.477,921,4.87,922,5.466,923,3.949,924,5.466,925,7.142,926,4.477]],["tags/13",[]],["title/14",[158,5.277]],["content/14",[3,1.514,30,1.711,33,4.559,41,1.972,94,2.924,102,2.342,166,2.999,285,2.492,302,3.72,305,3.452,307,2.904,330,4.559,401,4.141,402,4.334,416,6.972,425,5.99,597,3.972,760,4.334,770,2.602,849,4.829,894,5.621,927,6.31,928,6.31,929,5.99,930,6.31,931,6.31,932,6.31]],["tags/14",[]],["title/15",[58,1.396,62,0.725,63,1.426,69,1.241,92,1.218]],["content/15",[5,2.42,401,5.082,402,5.318]],["tags/15",[]],["title/124",[778,1.306,933,2.881]],["content/124",[]],["tags/124",[778,0.269,934,1.119,935,1.119]],["title/125",[936,4.655]],["content/125",[1,1.361,5,1.708,8,1.022,18,1.84,19,3.484,20,2.901,41,1.708,45,3.587,46,1.748,47,1.209,48,1.806,55,2.159,106,3.441,125,3.311,176,3.142,210,2.205,244,2.818,247,4.477,293,1.988,307,2.651,335,2.029,341,3.088,414,3.311,554,3.311,558,3.194,778,2.106,788,3.484,838,2.667,848,3.088,907,4.87,933,4.477,937,4.87,938,2.901,939,3.949,940,4.87,941,4.87,942,5.466,943,4.87,944,4.477,945,4.87,946,5.466,947,5.466,948,3.949,949,3.949,950,5.466]],["tags/125",[]],["title/126",[30,1.272,311,1.852,335,1.741]],["content/126",[1,1.684,3,1.762,30,1.366,36,3.305,51,1.663,55,2.671,91,1.601,95,3.459,133,4.486,210,2.031,242,3.17,246,3.17,261,3.854,285,1.988,296,3.854,327,2.672,335,1.869,384,3.3,393,3.638,399,3.854,412,2.755,458,3.638,545,4.887,595,3.305,683,2.223,778,2.264,789,3.39,792,3.459,797,4.258,912,3.822,933,4.835,951,5.036,952,4.486,953,5.54,954,5.036,955,5.036,956,5.036,957,3.05,958,2.943,959,5.036,960,5.036]],["tags/126",[]],["title/127",[558,2.741,788,2.288,961,4.69]],["content/127",[1,1.157,3,1.833,8,0.869,18,2.467,20,2.466,30,1.26,36,3.049,41,1.452,45,3.049,48,2.829,51,1.535,67,2.329,157,1.625,260,2.815,293,1.69,307,2.931,312,1.959,341,3.618,348,3.049,362,4.809,393,3.357,451,2.542,683,2.051,714,2.542,738,2.925,770,1.916,778,1.541,788,3.124,848,2.625,853,3.556,912,2.625,933,2.466,938,3.399,943,6.529,962,4.646,963,6.785,964,2.466,965,4.646,966,3.556,967,5.033,968,2.925,969,3.556,970,3.806,971,4.14,972,4.901,973,4.646,974,4.14,975,4.646,976,4.14,977,4.646,978,4.646,979,4.646,980,4.646]],["tags/127",[]],["title/128",[117,1.862,880,3.562]],["content/128",[3,1.898,8,0.585,46,1.602,47,0.692,48,2.162,49,1.766,51,1.584,61,1.678,62,0.615,100,1.348,117,2.816,118,1.449,132,2.34,163,1.289,176,1.894,217,3.929,259,3.294,293,1.137,307,1.78,327,1.659,334,1.678,341,4.522,391,4.467,421,1.348,521,2.785,535,1.827,597,3.02,611,3.671,614,3.02,646,1.611,648,1.894,677,2.28,738,3.02,786,3.148,838,1.525,847,1.71,880,3.83,963,3.929,964,2.546,967,2.147,981,2.393,982,3.929,983,3.126,984,4.273,985,4.273,986,3.126,987,3.126,988,2.785,989,3.126,990,4.273,991,4.273,992,3.126,993,3.126,994,3.126,995,3.126,996,3.466,997,3.126,998,2.259,999,3.126,1000,4.797,1001,3.126,1002,3.126,1003,3.126,1004,2.393,1005,3.671,1006,3.126,1007,3.126,1008,3.126,1009,3.126,1010,5.361,1011,4.797,1012,3.126,1013,3.126,1014,2.147,1015,1.71,1016,1.827,1017,2.906,1018,4.273,1019,3.126,1020,3.126,1021,3.126,1022,3.126,1023,3.126,1024,4.797,1025,4.797,1026,3.126,1027,4.797,1028,4.797,1029,3.126,1030,3.126,1031,3.126,1032,3.126,1033,3.126,1034,3.126]],["tags/128",[]],["title/129",[41,1.29,45,2.709,307,1.532,938,2.191]],["content/129",[]],["tags/129",[]],["title/130",[1035,5.74]],["content/130",[0,2.464,1,0.893,3,1.842,8,0.995,13,1.798,18,2.135,35,1.622,40,1.963,41,1.121,46,1.718,48,2.095,50,1.479,51,1.185,54,1.904,62,1.047,67,1.798,79,1.479,88,2.173,91,0.849,94,1.662,117,2.176,138,1.898,147,3.654,148,1.387,153,2.243,155,1.75,157,1.255,163,2.194,176,2.505,190,4.358,239,2.258,295,1.963,305,2.911,308,2.258,311,1.416,312,1.512,313,1.416,362,2.354,380,2.596,398,1.142,414,2.173,417,2.258,422,2.464,466,2.591,487,2.354,513,2.938,545,2.591,577,1.798,615,2.464,623,2.938,630,2.938,647,2.745,679,2.026,770,1.479,778,1.689,779,2.258,810,2.745,812,2.824,853,2.745,877,4.072,898,3.223,933,3.724,938,1.904,949,2.591,967,2.464,970,2.938,971,3.195,1035,3.195,1036,2.591,1037,2.938,1038,3.587,1039,6.343,1040,3.195,1041,4.74,1042,2.591,1043,3.587,1044,2.745,1045,2.745,1046,3.587,1047,4.358,1048,3.587,1049,2.464,1050,2.938,1051,5.195,1052,3.587,1053,6.343,1054,3.587,1055,3.587,1056,3.587,1057,2.464,1058,3.195,1059,3.195,1060,3.587,1061,3.587,1062,2.938,1063,3.587,1064,2.173]],["tags/130",[]],["title/131",[1065,6.443]],["content/131",[3,1.874,8,0.627,9,2.565,13,1.68,18,2.05,19,1.635,21,2.03,23,1.553,38,2.745,40,1.834,41,1.047,45,2.2,46,1.491,48,1.107,49,1.894,55,1.997,68,2.565,79,1.382,91,0.793,95,3.474,101,3.184,114,2.565,117,2.626,134,2.986,147,4.183,148,1.956,153,2.568,163,1.382,165,2.422,176,1.324,200,2.302,239,2.11,262,1.635,265,2.2,269,2.986,291,2.11,302,1.593,307,1.244,308,2.11,312,1.413,313,1.324,380,1.635,394,2.302,398,1.61,443,2.302,446,2.956,535,1.959,547,2.03,562,4.662,586,2.11,615,2.302,677,1.593,679,2.857,683,1.48,690,2.745,725,2.302,738,2.11,754,3.319,778,1.217,788,2.467,817,1.894,847,1.834,858,2.565,877,2.565,880,2.2,898,3.064,933,1.779,938,3.864,957,2.03,1016,1.959,1036,2.422,1040,2.986,1042,2.422,1049,2.302,1066,3.352,1067,3.352,1068,3.352,1069,3.352,1070,3.352,1071,2.745,1072,3.352,1073,2.745,1074,3.352,1075,4.506,1076,4.142,1077,3.352,1078,4.989,1079,6.091,1080,3.352,1081,3.352,1082,2.302,1083,2.302,1084,5.058,1085,6.784,1086,6.784,1087,3.352,1088,3.352,1089,3.352,1090,2.986,1091,2.986,1092,2.745]],["tags/131",[]],["title/132",[1093,4.836,1094,4.836]],["content/132",[1,0.513,3,1.908,8,0.385,16,2.007,18,1.156,20,1.094,40,1.128,41,0.644,46,1.401,47,0.456,50,1.821,54,1.823,58,0.781,75,1.164,101,1.297,102,0.765,117,2.249,118,0.955,132,2.513,138,0.735,147,1.416,148,3.098,153,2.413,156,1.688,157,0.721,163,0.85,172,0.932,176,0.814,255,1.353,279,1.577,312,1.448,313,0.814,320,1.164,334,0.721,341,1.164,396,1.688,398,1.822,407,1.836,417,2.162,487,2.254,497,1.688,502,1.688,522,1.688,531,2.416,535,1.204,547,1.249,554,1.249,568,1.577,589,1.416,595,1.353,630,2.813,631,2.813,675,3.033,677,0.98,679,1.941,719,1.688,725,1.416,730,1.836,754,2.254,756,3.934,757,3.934,758,1.836,759,1.836,760,1.416,761,1.836,762,1.688,763,1.836,764,3.934,765,1.836,766,1.836,770,0.85,778,0.496,842,3.06,843,1.836,844,1.489,845,1.836,847,1.128,848,1.164,902,1.416,906,1.416,933,1.823,963,1.688,1014,3.538,1015,2.819,1016,1.204,1017,2.081,1037,1.688,1042,1.489,1078,1.688,1082,1.416,1083,1.416,1093,3.06,1094,1.836,1095,2.061,1096,2.061,1097,1.836,1098,2.629,1099,3.06,1100,1.577,1101,3.06,1102,1.941,1103,2.819,1104,3.435,1105,1.489,1106,1.164,1107,2.061,1108,2.061,1109,2.061,1110,2.061,1111,3.435,1112,2.061,1113,2.061,1114,3.435,1115,2.061,1116,1.836,1117,3.435,1118,2.061,1119,2.061,1120,2.061,1121,1.489,1122,2.061,1123,2.061,1124,2.061,1125,2.061,1126,1.836,1127,2.061,1128,2.061,1129,2.061,1130,2.061,1131,2.061,1132,2.061,1133,2.061,1134,1.836,1135,1.489,1136,2.061,1137,1.353,1138,2.061,1139,2.061,1140,1.836,1141,1.577,1142,1.128,1143,2.061,1144,1.688,1145,2.061,1146,2.061,1147,2.061,1148,2.061,1149,1.836,1150,2.061,1151,2.061,1152,3.435,1153,3.435,1154,2.061,1155,3.435,1156,2.061,1157,2.061,1158,2.061,1159,2.061,1160,2.061,1161,1.489,1162,2.061,1163,2.061,1164,2.061,1165,2.061,1166,2.061,1167,2.061,1168,2.061,1169,2.061,1170,2.061,1171,2.061,1172,2.061,1173,2.061,1174,2.061,1175,1.577,1176,2.061,1177,1.836,1178,2.061,1179,1.577,1180,1.353,1181,3.38,1182,2.061,1183,3.243,1184,1.836,1185,2.061,1186,1.688,1187,1.688,1188,1.353,1189,2.061,1190,1.836,1191,1.836,1192,1.688,1193,1.836]],["tags/132",[]],["title/133",[1194,6.443]],["content/133",[0,2.552,1,0.564,3,1.886,8,0.883,13,1.136,16,1.325,18,1.589,24,1.373,32,1.638,46,1.337,47,0.501,50,0.935,51,0.749,58,0.859,85,2.019,88,2.251,90,1.168,101,2.339,117,2.609,118,3.169,132,2.664,148,2.941,153,0.956,155,1.106,157,0.793,163,0.935,172,2.928,176,2.157,223,2.438,234,1.638,244,1.168,245,1.488,252,1.427,262,1.106,265,2.438,293,0.825,295,1.24,305,1.24,313,0.895,317,3.412,331,1.638,341,1.281,398,1.503,421,0.978,430,1.373,445,1.735,458,1.638,497,1.856,531,2.584,554,1.373,558,1.325,568,1.735,589,1.557,628,1.638,677,1.077,679,2.099,690,1.856,725,1.557,748,1.488,754,2.438,778,0.894,788,1.106,812,1.203,823,1.427,835,1.557,838,1.106,844,1.638,847,1.24,933,1.972,938,2.506,939,1.638,948,1.638,964,1.203,968,1.427,972,1.735,996,2.685,998,1.638,1014,2.552,1015,2.988,1016,1.325,1017,1.373,1042,1.638,1058,2.019,1078,1.856,1082,1.557,1083,1.557,1105,1.638,1106,2.099,1142,1.24,1144,1.856,1175,1.735,1179,1.735,1180,2.438,1181,2.844,1183,2.339,1188,1.488,1195,2.019,1196,2.267,1197,2.267,1198,2.267,1199,1.427,1200,2.267,1201,2.267,1202,2.019,1203,2.267,1204,2.267,1205,3.716,1206,2.267,1207,2.267,1208,1.638,1209,1.735,1210,2.267,1211,3.867,1212,3.716,1213,2.267,1214,1.856,1215,2.019,1216,3.716,1217,2.019,1218,3.716,1219,2.267,1220,2.267,1221,1.638,1222,4.207,1223,2.267,1224,2.267,1225,2.267,1226,2.267,1227,3.716,1228,2.267,1229,2.019,1230,2.267,1231,2.267,1232,2.267,1233,3.716,1234,2.267,1235,2.267,1236,2.267,1237,2.267,1238,2.267,1239,2.267,1240,2.267,1241,2.267,1242,2.267,1243,2.267,1244,2.267,1245,2.267,1246,1.427,1247,1.735,1248,2.267,1249,3.716,1250,3.716,1251,3.716,1252,2.267,1253,2.552,1254,1.735,1255,2.267,1256,1.427,1257,2.267,1258,2.267,1259,2.267,1260,3.31,1261,2.267,1262,2.685,1263,2.267,1264,2.844,1265,2.267,1266,2.267,1267,1.856,1268,2.019,1269,2.267,1270,2.019,1271,2.019,1272,2.019,1273,2.267]],["tags/133",[]],["title/134",[1274,6.443]],["content/134",[0,4.589,8,1.249,37,2.292,48,2.207,51,2.207,91,1.581,92,2.207,125,4.047,176,3.201,262,3.259,265,4.384,334,2.835,337,2.638,350,2.695,398,2.58,595,4.384,612,5.952,679,3.774,851,5.952,855,5.113,938,3.546]],["tags/134",[]],["title/135",[19,2.288,125,2.841,176,1.852]],["content/135",[3,1.913,12,1.794,18,1.454,40,1.496,41,1.35,46,1.623,47,0.956,100,2.626,117,2.532,125,3.688,138,0.975,147,2.967,148,2.354,153,1.152,163,1.127,172,1.236,213,2.092,223,1.794,258,1.451,312,1.152,313,1.079,384,1.333,526,1.877,562,2.092,586,1.721,677,1.299,778,0.658,817,3.746,847,1.496,853,3.307,938,2.293,949,1.975,964,1.451,981,2.092,998,1.975,1014,2.967,1015,2.931,1016,1.597,1017,1.656,1018,2.435,1082,1.877,1083,1.877,1090,2.435,1091,5.906,1102,3.746,1105,1.975,1106,1.544,1142,2.364,1161,4.398,1187,4.986,1188,1.794,1208,1.975,1246,1.721,1247,2.092,1260,2.435,1262,1.975,1275,2.733,1276,2.435,1277,2.733,1278,2.733,1279,2.733,1280,2.435,1281,3.307,1282,1.975,1283,1.975,1284,2.435,1285,2.733,1286,2.733,1287,4.32,1288,2.733,1289,2.733,1290,4.32,1291,2.733,1292,2.733,1293,7.048,1294,2.733,1295,4.32,1296,6.087,1297,2.733,1298,5.423,1299,2.733,1300,6.087,1301,6.087,1302,2.733,1303,6.087,1304,6.087,1305,2.733,1306,2.733,1307,2.733,1308,2.733,1309,2.092,1310,2.733,1311,4.32,1312,2.733,1313,2.733,1314,2.733,1315,2.733,1316,2.733,1317,2.733,1318,2.435,1319,2.239,1320,2.733,1321,2.733,1322,2.435]],["tags/135",[]],["title/136",[41,1.466,125,2.841,398,1.493]],["content/136",[3,1.925,8,0.124,12,0.818,18,0.223,20,0.352,35,1.005,37,0.227,41,0.207,46,1.086,47,0.492,50,1.241,60,0.402,91,0.295,94,0.307,103,0.503,107,1.11,114,0.507,117,2.201,118,3.427,125,0.755,132,3.347,148,3.15,153,1.542,157,0.232,163,0.916,166,0.315,170,0.591,172,1.781,176,0.262,190,0.543,213,0.507,223,0.818,225,0.507,228,1.02,230,1.11,239,0.784,258,0.352,262,0.323,271,0.455,279,0.507,285,0.262,288,0.455,295,0.363,300,1.273,306,0.661,313,0.878,317,2.846,341,0.375,350,0.503,384,0.323,394,0.455,398,1.412,399,0.507,412,0.363,417,0.417,421,0.286,458,0.479,526,0.856,531,1.832,540,0.543,547,0.402,548,0.953,554,0.402,562,0.507,581,1.109,588,0.375,591,0.543,615,0.455,617,0.591,619,0.435,620,0.479,624,0.417,677,0.315,683,0.293,703,1.273,706,2.159,711,0.704,714,0.363,723,0.375,725,0.455,754,1.459,770,0.273,778,0.16,794,0.953,816,0.375,819,0.435,844,1.273,847,0.363,848,0.704,898,0.402,937,0.591,938,0.661,958,0.387,964,0.935,968,0.417,972,0.953,996,1.905,998,1.273,1014,3.34,1015,3.118,1016,0.387,1017,1.823,1042,0.9,1064,0.402,1082,1.21,1083,0.856,1097,0.591,1098,0.953,1099,1.57,1102,0.996,1105,1.273,1106,0.996,1134,0.591,1137,2.4,1140,0.591,1141,1.349,1142,0.363,1144,1.82,1149,0.591,1161,1.273,1177,0.591,1179,2.018,1180,1.459,1181,3.213,1183,2.793,1184,1.57,1186,1.02,1187,0.543,1188,2.755,1190,2.983,1191,1.57,1208,0.479,1211,2.159,1222,0.591,1246,1.894,1253,0.455,1254,0.507,1256,2.302,1262,0.9,1264,0.953,1271,1.57,1272,0.591,1280,0.591,1309,0.953,1318,1.98,1319,0.543,1322,0.591,1323,0.591,1324,0.663,1325,0.663,1326,0.663,1327,0.663,1328,0.663,1329,3.593,1330,1.246,1331,1.246,1332,0.663,1333,0.663,1334,2.223,1335,0.663,1336,0.663,1337,0.663,1338,2.223,1339,0.663,1340,0.663,1341,0.663,1342,1.11,1343,0.953,1344,0.663,1345,1.246,1346,0.663,1347,0.663,1348,0.663,1349,0.663,1350,2.223,1351,0.663,1352,0.663,1353,2.983,1354,2.983,1355,2.983,1356,0.663,1357,0.663,1358,1.762,1359,0.663,1360,0.663,1361,0.663,1362,0.663,1363,0.663,1364,0.663,1365,0.663,1366,1.762,1367,4.198,1368,1.98,1369,0.663,1370,2.223,1371,0.663,1372,0.663,1373,0.663,1374,0.663,1375,0.663,1376,0.663,1377,0.663,1378,0.663,1379,0.663,1380,0.663,1381,0.663,1382,0.663,1383,0.663,1384,0.663,1385,0.663,1386,2.223,1387,0.663,1388,0.507,1389,0.663,1390,0.591,1391,1.762,1392,1.762,1393,1.762,1394,0.663,1395,0.663,1396,0.543,1397,1.246,1398,0.663,1399,0.663,1400,1.246,1401,0.663,1402,0.591,1403,1.11,1404,0.543,1405,0.507,1406,0.663,1407,0.663,1408,1.762,1409,0.663,1410,0.663,1411,0.591,1412,0.663,1413,1.11,1414,1.762,1415,0.591,1416,0.663,1417,0.591,1418,0.663,1419,1.762,1420,0.591,1421,1.246,1422,0.663,1423,1.246,1424,0.663,1425,1.246,1426,0.663,1427,0.663,1428,0.663,1429,1.246,1430,2.636,1431,0.663,1432,1.11,1433,1.246,1434,0.663,1435,0.663,1436,0.663,1437,0.663,1438,0.953,1439,0.663,1440,0.663,1441,0.591,1442,0.663,1443,0.663,1444,0.663,1445,0.663,1446,0.663,1447,0.591,1448,0.663,1449,0.591,1450,0.663,1451,0.663,1452,0.663,1453,0.663,1454,0.663,1455,0.663,1456,0.663,1457,0.663,1458,0.663,1459,0.663,1460,0.663,1461,0.663,1462,0.663,1463,0.663,1464,0.663,1465,0.663,1466,0.663,1467,0.663,1468,0.591,1469,0.591,1470,0.663,1471,1.246,1472,0.663,1473,0.663,1474,0.663,1475,0.455,1476,0.663,1477,0.663,1478,0.663,1479,0.663,1480,0.663,1481,0.663,1482,0.507,1483,1.762,1484,0.663,1485,0.663,1486,2.223,1487,0.663,1488,3.348,1489,0.417,1490,0.455,1491,0.663,1492,0.663,1493,0.663,1494,0.663,1495,0.663,1496,0.663,1497,1.246,1498,1.246,1499,1.246,1500,1.246,1501,0.663,1502,1.246,1503,0.663,1504,1.246,1505,1.246,1506,1.762,1507,1.762,1508,0.663,1509,1.246,1510,0.663,1511,1.57,1512,1.11,1513,0.663,1514,0.663,1515,0.663,1516,0.543,1517,0.663,1518,0.663,1519,0.663,1520,0.663,1521,1.246,1522,0.663,1523,0.663,1524,0.663,1525,1.246,1526,0.663,1527,2.223,1528,1.246,1529,0.663,1530,1.246,1531,1.246,1532,0.663,1533,0.663,1534,3.348,1535,0.663,1536,0.663,1537,0.663,1538,1.246,1539,0.663,1540,0.663,1541,1.246,1542,1.762,1543,0.663,1544,0.663,1545,1.246,1546,0.663,1547,0.663,1548,0.663,1549,0.663,1550,0.663,1551,0.663,1552,0.543,1553,0.663,1554,0.663,1555,1.246,1556,0.663,1557,0.663,1558,0.663,1559,0.663,1560,0.663,1561,0.663,1562,0.591,1563,1.98,1564,1.246,1565,0.663,1566,0.663,1567,1.57,1568,0.663,1569,0.663,1570,0.663,1571,0.663,1572,1.246,1573,0.663,1574,0.663,1575,0.663,1576,1.246,1577,0.663,1578,0.663,1579,1.246,1580,0.663,1581,0.663,1582,0.663,1583,0.663,1584,0.663,1585,0.663,1586,0.663,1587,1.246,1588,0.543,1589,1.246,1590,0.507,1591,0.663,1592,0.663,1593,0.663,1594,0.663,1595,0.543,1596,0.663,1597,0.663,1598,0.663,1599,0.663,1600,0.663,1601,0.663,1602,0.663,1603,0.663,1604,0.663,1605,0.663,1606,0.663,1607,0.663,1608,0.663,1609,2.223,1610,0.663,1611,0.663,1612,0.663,1613,0.663,1614,1.246,1615,0.663,1616,0.663,1617,0.663,1618,1.246,1619,0.663,1620,0.663,1621,0.663,1622,1.246,1623,1.246,1624,0.663,1625,0.663,1626,0.663,1627,0.663,1628,0.663,1629,0.663,1630,0.663,1631,0.663,1632,0.663,1633,0.663,1634,0.663,1635,0.507,1636,0.663]],["tags/136",[]],["title/137",[398,1.728,1208,3.922]],["content/137",[1,0.243,3,1.92,8,0.334,13,0.489,18,0.6,20,0.947,27,0.662,30,0.484,35,0.442,39,0.641,40,0.534,46,0.866,47,0.395,48,1.169,50,0.403,51,0.589,71,1.939,75,0.552,79,0.403,91,0.231,102,0.662,117,2.037,118,3.119,124,0.671,132,2.571,144,0.671,147,0.671,148,3.11,153,2.107,157,0.861,163,0.735,172,1.375,176,0.704,200,0.671,213,0.747,223,0.641,262,0.476,271,0.671,272,1.779,284,0.403,285,0.704,293,0.355,295,0.534,298,0.362,302,0.848,303,0.705,306,1.307,307,1.129,309,0.671,313,0.704,317,1.289,336,0.947,349,0.489,350,0.394,352,0.641,364,3.335,373,0.87,384,0.87,398,1.591,412,0.534,413,0.827,422,0.671,443,1.691,451,0.534,473,1.461,540,0.8,554,1.081,561,0.641,577,0.894,581,3.146,584,0.947,588,3.802,592,1.123,605,1.365,609,2.197,614,0.615,619,0.641,647,0.747,692,0.747,714,1.347,723,2.653,746,0.552,748,1.616,778,0.957,787,1.779,788,1.201,789,0.489,794,0.747,816,0.552,820,0.8,830,0.8,835,0.671,838,0.87,844,1.289,847,0.534,868,3.154,920,0.8,933,1.879,938,1.614,939,2.197,941,0.87,958,1.042,964,0.518,969,0.747,970,0.8,996,0.705,998,0.705,1014,1.691,1015,2.384,1017,0.591,1057,0.671,1082,0.671,1098,1.365,1100,0.747,1101,0.87,1105,0.705,1106,0.552,1116,0.87,1137,1.171,1141,0.747,1179,1.365,1180,1.616,1181,1.885,1183,1.55,1188,0.641,1208,3.807,1211,1.461,1214,0.8,1215,0.87,1217,0.87,1246,1.55,1247,0.747,1253,0.671,1254,0.747,1256,1.914,1262,1.289,1264,0.747,1298,2.709,1329,2.089,1353,2.194,1354,2.194,1355,2.194,1368,0.87,1388,0.747,1390,0.87,1396,0.8,1403,1.589,1404,0.8,1405,1.365,1415,0.87,1447,0.87,1449,0.87,1468,0.87,1469,0.87,1482,1.885,1489,0.615,1562,0.87,1563,0.87,1567,0.87,1637,0.976,1638,0.747,1639,0.976,1640,0.976,1641,0.976,1642,1.784,1643,0.976,1644,0.976,1645,0.976,1646,0.8,1647,0.976,1648,1.784,1649,0.87,1650,0.976,1651,1.589,1652,0.976,1653,1.784,1654,0.87,1655,0.976,1656,0.87,1657,0.747,1658,0.976,1659,1.779,1660,1.589,1661,1.784,1662,3.041,1663,5.514,1664,4.696,1665,2.462,1666,0.976,1667,1.784,1668,2.462,1669,3.041,1670,3.975,1671,2.462,1672,3.041,1673,3.041,1674,0.976,1675,0.976,1676,1.784,1677,3.041,1678,1.784,1679,0.976,1680,1.784,1681,2.089,1682,2.462,1683,3.041,1684,0.976,1685,0.976,1686,0.976,1687,3.041,1688,3.825,1689,1.784,1690,0.8,1691,0.976,1692,2.462,1693,0.976,1694,0.87,1695,0.976,1696,0.705,1697,0.976,1698,0.976,1699,1.784,1700,0.976,1701,0.976,1702,1.589,1703,3.041,1704,0.976,1705,1.784,1706,0.976,1707,0.976,1708,0.976,1709,0.976,1710,0.976,1711,0.976,1712,1.589,1713,0.976,1714,0.976,1715,0.976,1716,0.976,1717,0.976,1718,0.976,1719,0.976,1720,0.976,1721,0.976,1722,0.976,1723,0.976,1724,0.976,1725,2.462,1726,1.784,1727,0.976,1728,0.976,1729,0.976,1730,0.976,1731,0.976,1732,1.784,1733,1.784,1734,1.784,1735,1.784,1736,0.976,1737,0.87,1738,0.87,1739,0.976,1740,1.589,1741,0.87,1742,0.87,1743,1.784,1744,0.87,1745,0.976,1746,0.976,1747,0.976,1748,0.976,1749,0.976,1750,0.976,1751,0.976,1752,0.976,1753,0.976,1754,0.976,1755,0.976,1756,0.976,1757,0.976,1758,0.976,1759,0.976,1760,0.976,1761,0.976,1762,0.976,1763,0.976,1764,0.976,1765,0.976,1766,0.976,1767,0.976,1768,0.976,1769,0.976,1770,0.976,1771,0.976,1772,0.976,1773,0.976,1774,0.976,1775,0.976,1776,0.976,1777,0.976,1778,0.976,1779,0.976,1780,0.976,1781,0.976,1782,0.8,1783,0.976,1784,0.976,1785,0.976,1786,0.976,1787,0.976,1788,0.671,1789,0.87,1790,0.976,1791,0.976]],["tags/137",[]],["title/138",[284,2.238,522,4.446]],["content/138",[3,1.883,16,2.032,18,1.75,24,3.772,51,1.717,62,1.023,67,1.743,71,1.696,112,2.282,117,1.193,148,1.344,176,3.4,194,2.661,265,2.282,284,1.434,293,1.265,298,1.29,306,3.305,307,1.29,334,1.216,336,3.667,349,1.743,387,2.512,398,1.982,526,2.388,548,4.766,577,1.743,580,1.653,589,2.388,646,3.21,683,1.535,714,3.407,762,4.258,770,1.434,778,1.251,796,2.661,832,3.098,873,2.661,880,2.282,933,3.305,938,4.488,968,2.189,969,4.766,972,2.661,988,3.098,990,6.156,991,4.632,1256,2.189,1388,4.766,1681,2.388,1792,2.661,1793,3.477,1794,4.632,1795,3.477,1796,3.477,1797,3.477,1798,5.199,1799,3.477,1800,5.199,1801,3.477,1802,6.227,1803,5.1,1804,3.477,1805,5.199,1806,6.227,1807,3.477,1808,3.477,1809,3.477,1810,3.477,1811,3.477,1812,3.477,1813,3.477,1814,3.477,1815,3.477,1816,3.477]],["tags/138",[]],["title/139",[1817,6.443]],["content/139",[1,1.506,125,3.664,176,3.01,263,3.718,272,4.37,273,4.154,284,3.143,312,2.55,349,3.032,381,4.954,465,5.389,473,4.954,576,4.954,579,4.954,588,3.417,609,4.37,679,3.417,714,3.309,746,3.417,778,1.834,794,4.629,895,4.954,933,4.045,938,3.21,939,4.37,944,4.954,953,4.954,1657,4.629,1660,5.389,1688,4.629,1818,6.048,1819,6.048,1820,5.389,1821,6.048,1822,6.048]],["tags/139",[]],["title/140",[49,3.067,590,4.155]],["content/140",[1,1.406,8,1.364,19,2.755,23,3.381,27,2.096,39,3.706,67,3.656,90,2.911,176,2.23,244,2.911,266,5.271,273,3.879,298,2.096,312,2.381,421,2.436,527,5.031,607,3.09,778,2.18,838,3.943,848,4.122,933,4.693,938,3.872,1823,5.647,1824,4.322,1825,5.647,1826,5.647,1827,5.647,1828,5.647,1829,5.647,1830,5.647,1831,5.647,1832,5.031,1833,5.647,1834,5.647,1835,5.031]],["tags/140",[]],["title/141",[58,1.396,62,0.725,63,1.426,69,1.241,92,1.218]],["content/141",[5,2.42,778,1.864,933,4.11]],["tags/141",[]],["title/43",[1,0.695,61,0.976,91,0.661,157,1.536,784,1.399,789,1.399,805,1.294]],["content/43",[1,1.743,8,1.309,47,1.549,61,2.916,157,2.449,247,6.828,307,2.598,312,2.952,552,5.358,580,3.328,620,5.058,805,4.126,1836,5.358]],["tags/43",[805,1.213]],["title/44",[47,0.913,61,1.444,243,1.962,1836,3.16]],["content/44",[1,1.755,27,2.616,30,1.912,47,1.56,53,6.28,61,2.466,79,2.907,91,1.668,243,3.351,256,3.112,258,3.741,1836,5.395,1837,7.049,1838,7.049,1839,7.049,1840,7.049]],["tags/44",[]],["title/45",[157,1.899,805,2.516]],["content/45",[1,2.205,8,1.062,41,2.288,57,3.727,90,2.927,157,2.834,258,3.014,259,3.9,298,2.108,306,3.014,307,2.108,310,6.636,313,2.243,334,1.986,336,3.014,394,3.9,421,2.449,430,3.44,577,2.846,741,4.103,748,3.727,784,3.67,788,2.771,789,3.67,802,3.319,805,3.967,1004,5.603,1841,5.679,1842,5.679,1843,5.059,1844,5.679,1845,5.679,1846,5.679,1847,5.059,1848,4.651,1849,5.059]],["tags/45",[]],["title/46",[157,1.64,580,2.229,805,2.173]],["content/46",[1,1.346,3,1.906,27,2.007,41,1.69,46,1.736,47,1.196,61,1.892,91,1.28,117,2.715,157,1.892,307,2.007,334,1.892,398,1.721,746,3.056,770,2.23,784,2.711,789,2.711,802,3.161,805,2.506,1004,4.139,1010,6.881,1049,4.871,1836,4.139,1849,4.818,1850,7.093,1851,5.408,1852,5.408,1853,5.408,1854,5.408,1855,4.818,1856,5.408,1857,5.408,1858,5.408]],["tags/46",[]],["title/47",[61,2.253]],["content/47",[51,2.378,55,2.843,61,2.964,62,1.416,138,2.567,334,2.518,337,2.843,673,5.896,741,5.201,770,2.968,1859,5.896,1860,5.896]],["tags/47",[]],["title/48",[58,1.396,62,0.725,63,1.426,69,1.241,92,1.218]],["content/48",[5,2.402,61,2.688,157,2.688,805,3.562]],["tags/48",[]],["title/62",[1,1.028,62,0.812,138,1.472,1861,2.259]],["content/62",[]],["tags/62",[61,0.548,1861,0.858]],["title/63",[936,4.655]],["content/63",[1,1.621,5,2.035,30,1.766,60,4.833,61,2.791,62,1.697,77,6.535,138,3.077,705,5.8,809,4.983,848,3.678,878,5.8,886,5.8,1062,5.332,1861,4.365,1862,6.535,1863,4.704,1864,6.511,1865,4.704]],["tags/63",[]],["title/64",[335,2.015,1861,2.97]],["content/64",[3,1.092,18,1.901,23,2.617,27,2.096,35,2.554,41,1.765,51,2.41,67,2.831,72,3.706,88,3.421,116,3.421,256,2.493,258,2.997,260,3.421,298,2.096,302,3.467,334,2.552,335,3.282,336,2.997,421,2.436,504,5.031,508,5.031,640,5.031,729,3.879,784,2.831,822,3.09,869,3.706,1036,4.08,1861,4.422,1863,4.08,1866,4.322,1867,5.647,1868,5.647,1869,4.625,1870,5.647,1871,7.295,1872,7.295,1873,7.295,1874,3.879,1875,5.647]],["tags/64",[]],["title/65",[41,1.29,258,2.191,869,2.709,1861,2.259]],["content/65",[1,1.042,3,1.768,8,1.113,19,2.043,22,1.317,23,1.218,27,1.554,30,1.416,35,2.692,37,0.902,41,1.631,48,2.779,51,0.868,54,1.395,61,2.083,62,0.824,66,1.805,67,1.317,71,2.043,79,2.152,88,3.162,90,1.355,91,0.622,102,0.975,103,1.06,132,2.905,141,2.341,157,1.465,176,1.654,242,1.654,252,1.654,258,3.16,262,2.547,291,2.636,298,2.21,302,1.249,304,3.43,305,1.438,307,1.937,313,1.654,334,2.083,336,1.395,337,1.038,350,2.106,353,4.302,396,3.43,398,1.333,399,3.205,443,2.876,446,2.447,487,3.426,572,1.725,586,1.654,597,3.286,598,3.43,614,1.654,646,2.691,679,1.485,683,2.871,711,3.364,729,1.805,741,3.025,778,1.008,788,1.282,797,1.654,812,1.395,816,1.485,822,1.438,838,1.282,849,2.011,855,2.011,859,1.654,869,5.232,898,1.592,906,1.805,1036,3.025,1045,2.011,1199,1.654,1595,4.276,1654,2.341,1792,2.011,1861,3.977,1865,1.899,1866,2.011,1874,4.759,1876,2.628,1877,4.651,1878,2.628,1879,4.651,1880,2.152,1881,2.628,1882,4.188,1883,4.188,1884,4.977,1885,5.305,1886,4.651,1887,6.503,1888,1.899,1889,2.628,1890,3.205,1891,4.877,1892,1.654,1893,2.628,1894,2.152,1895,2.152,1896,2.628,1897,2.628,1898,2.628,1899,2.628,1900,2.628,1901,2.628]],["tags/65",[]],["title/66",[262,2.288,683,2.071,1861,2.566]],["content/66",[1,0.663,3,0.515,8,1.122,18,0.896,19,2.926,24,1.613,27,1.57,28,2.372,30,0.722,40,1.457,41,1.322,46,1.036,47,0.936,51,0.879,54,1.413,55,1.671,61,0.931,62,0.832,66,2.906,79,2.171,88,3.633,89,2.18,90,2.714,91,1.001,94,2.78,106,3.314,112,1.747,125,1.613,132,3.81,138,1.509,157,0.931,176,1.671,209,3.769,212,5.009,219,2.037,234,3.057,245,3.455,258,1.413,291,1.676,298,0.988,300,3.804,312,1.122,320,1.504,334,2.437,350,1.074,352,1.747,356,1.923,398,1.676,401,2.777,402,2.906,404,2.372,412,3.282,421,1.148,425,4.03,443,1.828,446,1.556,487,2.777,548,5.009,568,2.037,572,4.295,586,1.676,592,1.676,614,1.676,624,3.776,634,2.037,661,2.372,668,2.372,683,1.868,692,3.238,706,4.312,711,4.128,741,1.923,779,1.676,798,2.372,816,1.504,819,1.747,834,1.828,838,2.064,839,2.372,869,5.361,1059,2.372,1062,2.18,1199,3.314,1309,5.803,1413,2.372,1511,2.372,1512,2.372,1516,6.556,1595,2.18,1635,2.037,1656,2.372,1788,1.828,1861,1.457,1877,3.769,1879,2.372,1885,4.691,1886,5.344,1888,1.923,1891,2.18,1902,2.662,1903,2.662,1904,1.747,1905,2.662,1906,2.662,1907,2.662,1908,2.372,1909,6.545,1910,4.231,1911,2.662,1912,5.265,1913,4.231,1914,4.231,1915,4.231,1916,4.231,1917,4.231,1918,2.037,1919,2.037,1920,4.691,1921,3.238,1922,2.662,1923,2.662,1924,2.662,1925,2.662]],["tags/66",[]],["title/67",[1926,6.443]],["content/67",[1,1.89,3,1.163,8,1.42,23,3.519,30,2.059,61,2.656,62,1.183,67,3.806,73,4.29,77,4.925,79,2.479,91,1.423,138,2.144,244,3.099,261,4.602,268,4.13,313,2.374,413,2.787,451,3.29,638,4.78,645,4.925,809,5.812,1861,4.783,1862,6.219,1863,5.486,1927,6.013,1928,4.925]],["tags/67",[]],["title/68",[413,2.986]],["content/68",[1,1.805,8,1.355,30,1.966,61,2.536,268,4.979,313,2.863,451,3.967,638,5.357,1861,3.967,1862,5.937,1863,5.238]],["tags/68",[]],["title/69",[58,1.396,62,0.725,63,1.426,69,1.241,92,1.218]],["content/69",[5,2.42,243,3.68,1861,4.237]],["tags/69",[]],["title/57",[1929,4.446,1930,3.728]],["content/57",[]],["tags/57",[1930,1.077,1931,1.2]],["title/58",[936,4.655]],["content/58",[1,1.941,5,1.96,8,1.458,18,2.111,30,1.701,46,1.535,47,1.387,55,2.476,242,3.948,284,2.586,576,5.136,644,5.587,784,3.143,789,3.143,792,4.307,823,3.948,838,3.059,848,3.543,929,4.8,949,4.531,958,3.665,1121,6.129,1930,5.354,1931,4.8,1932,6.271,1933,6.271,1934,6.271,1935,6.385]],["tags/58",[]],["title/59",[30,1.472,210,2.19]],["content/59",[1,1.674,30,2.207,46,1.992,47,1.8,62,1.323,91,1.591,138,2.398,210,2.713,312,2.835,334,2.352,335,3.02,337,2.656,345,3.93,413,3.116,510,5.991,1888,4.859,1930,5.589,1936,6.725]],["tags/59",[]],["title/60",[284,2.238,285,2.144]],["content/60",[1,0.548,3,1.898,18,0.742,20,1.169,22,1.104,39,1.446,46,1.133,47,1.024,48,1.529,50,3.251,55,0.87,57,1.446,61,0.771,62,0.433,69,0.742,71,1.771,117,1.245,139,1.686,148,1.79,153,3.084,163,3.251,166,3.58,176,1.828,239,4.021,245,1.446,262,1.075,271,1.513,285,0.87,290,1.686,291,1.387,298,0.818,311,0.87,324,4.512,334,1.27,337,0.87,339,2.493,350,1.464,353,1.592,380,1.771,384,1.771,398,0.701,412,1.205,430,1.335,451,1.986,502,4.397,561,4.192,597,2.285,608,1.963,622,1.963,681,1.387,683,1.603,703,4.88,723,4.674,748,1.446,770,1.909,803,1.387,816,1.245,817,2.051,864,1.686,865,1.963,866,1.963,898,2.199,920,5.232,923,1.592,1071,1.804,1121,4.88,1309,2.778,1438,4.889,1489,2.285,1490,2.493,1590,1.686,1688,5.169,1874,2.493,1894,2.973,1921,2.778,1930,4.077,1931,3.543,1937,2.203,1938,1.804,1939,2.203,1940,1.804,1941,3.63,1942,2.203,1943,3.63,1944,3.63,1945,2.203,1946,2.203,1947,4.629,1948,3.63,1949,3.63,1950,2.203,1951,2.203,1952,2.203,1953,3.63,1954,2.203,1955,3.63,1956,2.203,1957,3.63,1958,3.63,1959,1.963,1960,3.63,1961,3.63,1962,2.203,1963,2.203,1964,2.203,1965,2.203,1966,2.203,1967,2.203,1968,2.203]],["tags/60",[]],["title/61",[58,1.396,62,0.725,63,1.426,69,1.241,92,1.218]],["content/61",[5,2.42,1929,6.342,1930,5.318]],["tags/61",[]],["title/70",[103,1.666,301,2.709,1969,3.678,1970,3.381]],["content/70",[]],["tags/70",[103,0.452,256,0.494,526,0.769]],["title/71",[]],["content/71",[8,1.313,9,4.075,37,1.827,46,1.922,47,1.737,48,2.319,51,1.759,55,2.772,79,2.195,103,3.168,114,4.075,263,2.597,284,2.195,293,1.937,301,4.607,307,1.976,315,4.168,496,3.847,586,3.352,595,3.494,596,4.743,614,3.352,621,4.361,824,4.361,831,4.743,848,3.008,879,6.254,880,4.607,889,4.361,902,4.821,1005,5.373,1199,3.352,1319,4.361,1323,4.743,1405,4.075,1638,4.075,1919,4.075,1970,4.361,1971,7.02,1972,5.324,1973,5.324,1974,5.324,1975,5.324,1976,4.361,1977,5.324,1978,5.324]],["tags/71",[]],["title/72",[256,2.397,1824,4.155]],["content/72",[26,3.163,37,2.248,46,1.96,47,1.772,66,4.5,69,2.206,243,3.114,256,2.893,260,3.969,301,4.3,309,4.5,312,2.763,401,4.3,577,3.284,619,4.3,805,3.037,812,3.478,1199,4.125,1824,5.015,1855,5.838,1979,6.552,1980,6.552,1981,6.552,1982,6.552]],["tags/72",[]],["title/73",[26,2.544]],["content/73",[8,0.518,13,1.389,18,0.933,21,2.645,22,1.389,23,1.284,26,1.094,27,1.621,37,1.854,39,1.818,41,0.866,46,1.633,47,1.476,51,2.026,57,1.818,66,1.903,73,1.565,79,1.142,90,1.428,93,2.468,102,1.621,103,2.993,105,1.516,165,2.002,166,1.317,172,1.253,175,2.468,208,2.468,210,1.118,219,2.12,226,2.269,229,2.002,243,1.317,246,1.744,254,2.999,256,1.928,258,1.47,266,2.002,277,2.468,283,5.465,284,1.142,285,2.134,286,4.426,293,1.008,297,5.464,298,1.028,301,1.818,302,1.317,304,2.269,305,2.389,307,2.477,308,1.744,311,2.422,315,2.868,320,1.565,322,3.342,324,1.619,327,1.47,334,1.89,335,2.754,336,2.317,337,1.094,341,3.77,342,3.342,349,1.389,387,2.002,413,3.092,417,2.749,437,3.89,448,2.269,451,1.516,485,2.269,491,2.269,515,3.89,561,1.818,577,1.389,588,1.565,589,1.903,607,1.516,609,2.002,620,2.002,634,2.12,714,1.516,732,2.468,770,1.8,788,2.13,799,3.155,812,1.47,819,1.818,822,1.516,828,3.89,834,1.903,858,2.12,859,1.744,872,2.002,903,5.023,1005,2.12,1516,2.269,1788,2.999,1792,2.12,1824,4.136,1865,3.155,1888,2.002,1890,2.12,1928,5.023,1983,2.002,1984,4.366,1985,2.269,1986,2.77,1987,2.77,1988,2.77,1989,2.77,1990,2.77,1991,2.77,1992,2.77,1993,5.945,1994,2.77,1995,2.77,1996,2.77,1997,2.77,1998,2.77,1999,2.77,2000,4.366,2001,2.77,2002,2.77,2003,2.77,2004,4.366,2005,2.77,2006,2.77,2007,2.77,2008,2.77,2009,2.77,2010,2.77,2011,2.77,2012,2.77,2013,2.77,2014,2.77,2015,4.366,2016,2.77,2017,2.77,2018,2.77,2019,2.269,2020,4.366,2021,2.77,2022,2.468,2023,2.77,2024,2.77,2025,2.77,2026,2.77,2027,2.77]],["tags/73",[]],["title/74",[58,1.396,62,0.725,63,1.426,69,1.241,92,1.218]],["content/74",[5,2.384,103,3.077,301,5.006,1969,6.796,1970,6.248]],["tags/74",[]],["title/49",[30,1.272,778,1.129,783,3.59]],["content/49",[1,1.663,13,3.349,26,2.638,27,2.479,30,2.366,46,1.635,47,1.793,62,1.314,79,2.755,138,2.383,298,2.479,307,2.479,334,2.337,558,3.904,746,3.774,778,1.951,926,5.472,1036,4.827,2028,5.472,2029,6.681]],["tags/49",[778,0.63]],["title/50",[413,2.986]],["content/50",[26,2.784,27,3.107,75,3.983,275,5.774,334,2.466,337,2.784,859,5.269,872,5.093,906,4.842,1193,6.28,2028,6.856,2030,7.049,2031,7.049]],["tags/50",[]],["title/51",[26,2.544]],["content/51",[]],["tags/51",[]],["title/52",[30,1.472,288,3.728]],["content/52",[1,1.857,55,2.946,242,4.697,784,3.74,789,3.74,792,5.124,1935,7.088]],["tags/52",[]],["title/53",[285,2.144,2032,5.428]],["content/53",[3,1.599,8,1.291,36,4.532,103,2.786,313,2.727,350,2.786,393,4.99,778,1.662,969,7.021,976,6.153,1209,5.286,1794,7.367,2033,6.153,2034,6.907]],["tags/53",[]],["title/54",[285,2.144,859,3.417]],["content/54",[46,1.668,47,1.815,337,3.239,340,4.923,398,2.611,451,4.815,607,3.729,778,1.974,822,3.729,1057,4.68,1076,6.718,2035,6.814,2036,6.814,2037,6.814]],["tags/54",[]],["title/55",[293,1.706,327,2.489,345,2.741]],["content/55",[1,0.902,3,1.838,8,0.678,30,1.454,35,3.404,37,1.244,46,1.313,47,1.186,48,1.197,61,2.467,62,0.713,79,1.495,100,1.564,103,2.163,217,2.969,248,2.282,259,2.49,285,1.431,294,3.683,306,2.846,311,2.118,315,1.924,316,2.774,327,1.924,334,1.268,336,1.924,345,3.134,350,2.163,384,1.768,421,2.313,432,3.229,443,2.49,503,3.229,595,2.379,611,4.104,638,4.44,714,1.983,774,1.983,778,1.812,786,2.379,789,2.688,826,3.229,859,2.282,880,2.379,939,3.875,982,2.969,984,3.229,985,3.229,1005,4.104,1420,3.229,1792,5.762,1895,2.969,2033,3.229,2038,3.625,2039,3.625,2040,3.625,2041,3.625,2042,3.625,2043,3.625,2044,3.625,2045,3.625,2046,3.625,2047,6.383,2048,3.625,2049,3.625,2050,6.707,2051,7.053,2052,5.363,2053,5.363,2054,5.363,2055,5.363,2056,3.625,2057,3.625,2058,3.625,2059,3.625,2060,3.229,2061,6.383,2062,3.625,2063,3.625,2064,3.625,2065,3.625,2066,3.625,2067,3.625,2068,3.625,2069,3.625]],["tags/55",[]],["title/56",[58,1.396,62,0.725,63,1.426,69,1.241,92,1.218]],["content/56",[5,2.402,30,2.084,778,1.85,783,5.882]],["tags/56",[]],["title/117",[2070,5.277]],["content/117",[]],["tags/117",[778,0.269,2070,0.917,2071,1.119]],["title/118",[936,4.655]],["content/118",[1,1.454,18,1.966,30,1.584,31,4.784,46,1.825,47,1.649,48,1.929,50,3.074,62,1.149,73,3.3,90,3.011,92,1.929,139,4.471,246,3.677,249,4.784,263,2.85,346,3.833,577,2.928,607,4.079,619,3.833,645,4.784,746,3.3,755,3.833,805,2.707,926,4.784,940,5.204,945,5.204,1888,4.22,2070,4.784,2072,5.841,2073,5.841,2074,5.841,2075,4.892,2076,5.841,2077,5.841,2078,5.204,2079,5.204,2080,5.841,2081,5.841,2082,5.204,2083,5.841]],["tags/118",[]],["title/119",[335,2.391]],["content/119",[1,1.759,3,1.762,5,1.137,16,2.126,18,1.81,27,1.35,30,1.458,37,2.194,41,1.137,46,1.565,47,1.668,48,1.776,51,1.776,55,2.123,61,1.881,62,1.058,69,1.81,73,3.038,90,1.875,91,0.861,94,1.686,103,2.58,105,1.99,116,2.204,193,2.98,210,2.169,242,2.29,244,1.875,246,2.29,260,2.204,262,1.775,284,1.5,285,1.437,295,1.99,306,1.931,310,2.98,311,2.123,312,1.534,313,1.437,334,1.881,335,2.374,337,1.437,350,2.58,384,1.775,413,1.686,451,1.99,466,2.628,544,2.29,551,3.241,683,1.606,709,3.241,746,2.055,773,2.784,778,1.814,789,3.206,792,2.499,797,2.29,816,2.055,817,3.038,821,3.738,823,2.29,838,1.775,848,2.055,893,3.241,895,2.98,912,3.038,1045,2.784,1199,2.29,1635,2.784,1860,2.98,1869,2.98,1920,3.241,1935,4.404,1940,2.98,1983,2.628,2019,2.98,2075,4.948,2082,4.79,2084,3.638,2085,3.638,2086,3.638,2087,4.895,2088,3.638,2089,5.377,2090,3.638,2091,5.377,2092,3.638,2093,3.638,2094,3.638,2095,3.241]],["tags/119",[]],["title/120",[2096,5.277]],["content/120",[0,2.396,1,0.869,3,1.913,8,0.652,44,1.909,46,1.813,47,1.153,50,1.439,92,1.152,101,3.281,105,1.909,117,2.666,118,2.892,132,3.044,148,2.864,153,2.198,163,1.439,172,1.578,176,1.378,200,2.396,225,2.67,235,2.521,239,3.928,352,2.29,398,2.203,531,2.852,584,1.852,588,1.971,677,1.658,683,1.54,793,2.858,796,2.67,806,2.196,821,2.039,838,1.702,847,2.852,898,3.157,964,1.852,1015,2.852,1016,2.039,1106,1.971,1221,2.521,1246,2.196,1253,2.396,1343,2.67,1438,3.989,1696,2.521,2075,4.862,2087,2.67,2096,6.365,2097,3.489,2098,3.489,2099,2.67,2100,3.108,2101,2.858,2102,2.858,2103,2.858,2104,2.67,2105,3.108,2106,6.924,2107,3.108,2108,3.108,2109,4.644,2110,3.108,2111,3.108,2112,3.108,2113,3.108,2114,3.108,2115,3.108,2116,3.108,2117,3.108,2118,2.858,2119,3.108]],["tags/120",[]],["title/121",[3,0.798,284,1.702,380,2.014,398,1.314]],["content/121",[1,1.438,3,1.899,8,0.466,18,0.839,20,1.323,24,2.432,32,1.801,44,3.161,46,1.55,47,0.552,50,1.028,54,1.323,55,1.585,62,0.49,71,1.216,75,1.409,91,0.59,105,1.364,117,2.691,118,2.678,132,2.459,138,0.889,148,2.752,153,1.051,155,1.216,163,2.791,172,1.815,176,1.585,244,1.285,254,2.757,284,2.935,295,1.364,305,1.364,312,1.051,336,1.323,349,1.25,352,1.636,380,2.819,398,2.154,412,2.197,421,1.075,531,2.197,553,1.801,554,1.51,557,4.128,584,3.066,595,1.636,628,1.801,646,1.285,677,1.908,678,1.57,680,1.636,683,1.101,711,1.409,713,2.221,714,2.197,723,2.268,726,2.221,728,2.221,738,2.527,754,2.635,755,1.636,784,1.25,787,2.901,789,2.012,805,2.678,822,1.364,847,2.197,948,1.801,952,3.577,957,1.51,964,1.323,1015,2.758,1016,1.457,1037,2.042,1064,1.51,1073,3.288,1106,2.268,1137,1.636,1141,1.908,1142,1.364,1180,1.636,1186,2.042,1188,1.636,1246,2.527,1253,1.712,1342,2.221,1343,1.908,1388,1.908,1681,3.462,1696,1.801,2075,1.636,2099,1.908,2101,2.042,2120,4.49,2121,2.221,2122,2.493,2123,2.042,2124,2.493,2125,2.493,2126,2.493,2127,5.778,2128,2.493,2129,2.493,2130,2.493,2131,2.493,2132,2.493,2133,2.493,2134,2.493,2135,2.493,2136,2.493,2137,2.493,2138,2.493,2139,2.493,2140,2.493,2141,2.493,2142,4.015,2143,2.493,2144,2.493,2145,2.221,2146,2.493,2147,2.493,2148,4.015,2149,2.493,2150,2.493,2151,2.493,2152,2.493,2153,2.493,2154,2.493,2155,2.493,2156,2.493]],["tags/121",[]],["title/122",[1064,3.288,2075,3.562]],["content/122",[3,1.915,18,0.702,19,2.173,21,1.264,23,0.967,24,1.264,44,1.142,46,1.614,47,0.985,50,0.86,62,0.41,67,1.046,73,1.179,92,0.689,117,1.781,118,3.515,124,3.565,132,2.173,148,2.999,153,2.189,157,0.73,163,0.86,172,0.943,176,0.824,200,1.433,222,1.597,223,1.369,225,1.597,228,1.709,234,3.218,239,2.804,262,1.018,284,1.431,291,1.313,320,1.179,384,1.018,398,1.418,421,0.9,531,2.84,557,2.842,577,1.046,584,1.107,588,1.179,677,0.992,711,1.179,746,1.179,754,2.277,755,1.369,770,0.86,806,2.184,821,2.028,835,3.059,838,1.693,847,1.899,891,1.859,898,2.102,953,1.709,964,1.107,1015,3.153,1016,1.219,1102,1.96,1106,1.96,1137,2.923,1183,1.313,1188,2.923,1221,1.507,1246,2.184,1253,2.383,1254,2.656,1262,1.507,1264,1.597,1267,1.709,1281,2.656,1282,1.507,1283,1.507,1343,1.597,1402,1.859,1432,3.091,1438,2.656,1696,1.507,1859,1.709,2075,4.326,2078,1.859,2079,1.859,2087,2.656,2096,4.252,2099,1.597,2100,1.859,2102,1.709,2103,1.709,2104,1.597,2105,1.859,2106,5.541,2107,1.859,2108,1.859,2109,3.091,2110,1.859,2111,1.859,2112,1.859,2113,1.859,2114,1.859,2115,1.859,2116,1.859,2117,1.859,2118,1.709,2119,1.859,2120,1.859,2145,1.859,2157,2.086,2158,2.086,2159,2.086,2160,2.086,2161,1.859,2162,4.454,2163,2.086,2164,2.086,2165,3.218,2166,2.086,2167,2.086,2168,1.859,2169,2.086,2170,3.47,2171,2.086,2172,2.086,2173,2.086,2174,2.086,2175,2.086,2176,2.086,2177,2.086,2178,2.086,2179,2.086,2180,2.086,2181,2.086,2182,2.086,2183,2.086,2184,3.47,2185,2.086,2186,2.086,2187,2.086,2188,2.086,2189,2.086,2190,2.086,2191,2.086,2192,2.086,2193,1.859,2194,3.47,2195,2.086,2196,2.086,2197,2.086,2198,2.086,2199,2.086,2200,2.086,2201,2.086,2202,2.086,2203,2.086,2204,2.086,2205,2.086,2206,2.086,2207,2.086,2208,2.086,2209,3.47,2210,2.086,2211,2.086]],["tags/122",[]],["title/123",[58,1.396,62,0.725,63,1.426,69,1.241,92,1.218]],["content/123",[5,2.384,46,1.867,47,1.688,2075,5.006,2087,5.838]],["tags/123",[]],["title/78",[2212,3.903]],["content/78",[1,1.926,8,1.158,26,2.446,30,2.288,41,1.936,49,3.5,50,2.554,51,2.046,55,2.446,92,2.046,245,4.066,256,2.735,263,3.022,313,2.446,535,4.521,619,4.066,646,3.988,677,2.944,678,4.871,784,3.105,789,3.105,792,4.255,804,5.074,981,4.741,1929,6.91,2212,3.753,2213,6.195,2214,6.195]],["tags/78",[677,0.532,2212,0.678,2215,1.119]],["title/79",[451,2.259,646,2.128,677,1.962,678,2.599]],["content/79",[1,1.428,3,1.893,7,2.609,8,0.743,13,1.235,16,1.44,18,0.829,21,1.492,23,1.142,24,1.492,27,0.914,30,0.668,37,0.845,41,0.77,46,1.404,48,1.313,51,0.814,73,1.392,84,2.018,91,0.941,100,1.062,106,1.551,117,1.968,144,1.692,148,2.603,153,1.676,155,3.071,157,2.202,163,2.366,210,0.994,211,2.018,239,2.503,252,1.551,265,1.617,272,1.78,284,1.639,288,1.692,293,1.818,306,1.307,307,1.855,309,1.692,313,0.973,327,1.307,334,1.748,337,0.973,352,1.617,380,1.202,387,1.78,394,1.692,398,1.265,409,2.018,441,2.195,446,1.44,451,3.444,466,1.78,475,2.018,524,2.018,544,1.551,553,1.78,580,1.171,589,1.692,597,1.551,634,1.885,646,2.957,647,1.885,677,3.617,678,3.612,680,1.617,683,1.088,711,1.392,731,2.195,738,2.503,748,3.281,770,1.016,779,1.551,784,1.993,786,1.617,788,1.94,789,1.993,805,2.659,817,1.392,822,1.348,847,3.444,850,2.195,898,1.492,912,2.246,967,1.692,1004,1.885,1010,5.156,1016,2.921,1041,3.542,1044,4.391,1051,3.256,1073,5.156,1083,2.731,1098,3.043,1221,2.873,1651,2.195,1694,2.195,1847,2.195,2104,3.043,2212,2.408,2216,2.463,2217,2.463,2218,2.195,2219,2.463,2220,2.463,2221,2.463,2222,2.463,2223,2.463,2224,2.463,2225,2.463,2226,2.463,2227,1.885,2228,2.463,2229,2.463,2230,2.018,2231,2.463,2232,2.463,2233,2.463,2234,2.463,2235,2.463,2236,2.463,2237,2.463,2238,2.195,2239,2.018,2240,3.542,2241,3.542,2242,3.976,2243,3.976,2244,2.463]],["tags/79",[]],["title/80",[91,1.285,2212,3.288]],["content/80",[3,1.894,8,1.11,18,0.641,32,1.375,41,1.303,44,1.042,46,1.692,47,0.711,48,1.377,51,1.062,54,1.01,55,0.752,56,1.559,62,0.632,88,1.153,91,1.405,117,2.687,118,1.932,132,1.568,138,0.679,148,2.843,153,0.803,157,1.458,163,3.032,166,1.527,172,1.886,176,0.752,210,0.768,223,1.249,235,1.375,263,1.568,288,2.207,302,1.527,306,1.01,307,0.707,312,1.355,313,0.752,335,0.707,337,1.269,357,1.559,364,1.457,380,2.67,531,2.282,535,1.113,577,2.743,582,1.696,584,1.705,615,1.307,646,3.79,648,1.153,677,1.527,678,3.084,711,1.076,714,3.911,733,1.696,738,1.198,755,1.249,770,1.325,779,1.198,889,1.559,921,1.696,949,1.375,957,1.153,964,1.705,967,1.307,1015,1.758,1017,1.153,1045,1.457,1071,1.559,1137,2.109,1142,1.042,1202,1.696,1214,1.559,1221,1.375,1246,1.198,1247,1.457,1256,1.198,1282,1.375,1588,1.559,1638,1.457,1649,2.863,1657,3.749,1696,1.375,1744,1.696,1848,1.559,1918,1.457,1985,1.559,2099,1.457,2101,1.559,2102,1.559,2103,1.559,2104,1.457,2212,4.563,2245,1.904,2246,3.715,2247,1.904,2248,1.904,2249,1.904,2250,3.715,2251,1.904,2252,3.213,2253,1.559,2254,1.696,2255,1.696,2256,3.715,2257,3.715,2258,2.863,2259,2.863,2260,3.715,2261,2.863,2262,2.863,2263,3.715,2264,1.696,2265,1.696,2266,1.696,2267,1.696,2268,1.696,2269,2.863,2270,2.863,2271,4.364,2272,3.715,2273,1.696,2274,4.17,2275,1.904,2276,1.904,2277,4.17,2278,1.904,2279,1.904,2280,1.904,2281,4.17,2282,3.213,2283,4.17,2284,4.17,2285,3.213,2286,4.17,2287,1.904,2288,1.904,2289,2.632,2290,1.696,2291,1.696,2292,1.559,2293,1.559,2294,1.559,2295,3.213,2296,1.904,2297,1.696,2298,1.904,2299,1.904,2300,1.904,2301,1.904,2302,3.213,2303,1.904,2304,1.904,2305,1.904,2306,1.904,2307,1.904,2308,1.904,2309,1.904,2310,1.904]],["tags/80",[]],["title/81",[2239,5.277]],["content/81",[1,0.586,3,1.875,8,0.717,37,0.808,46,0.938,47,0.521,48,2.032,50,0.971,51,0.778,73,1.331,91,1.147,96,1.803,103,1.547,117,2.385,143,2.098,148,2.897,153,0.993,155,1.149,163,2.866,172,1.065,191,1.929,245,1.546,285,0.93,288,1.618,305,1.289,313,0.93,315,1.25,324,1.377,334,0.824,335,0.874,337,0.93,345,1.377,350,0.95,356,1.702,362,1.546,380,2.366,381,1.929,398,1.779,413,1.777,446,1.377,451,1.289,535,1.377,544,1.483,561,1.546,577,1.922,580,1.12,591,1.929,646,1.976,648,1.427,677,1.12,678,1.483,703,1.702,714,3.366,748,1.546,770,0.971,803,1.483,822,1.289,890,2.098,958,2.241,967,2.633,968,1.483,1047,3.14,1051,3.14,1075,2.098,1076,4.577,1102,1.331,1121,2.77,1229,2.098,1396,1.929,1417,2.098,1441,2.098,1588,1.929,1635,1.803,1638,1.803,1657,1.803,1832,2.098,1866,1.803,1874,1.618,1884,2.935,1928,1.929,1931,3.711,1938,1.929,1959,2.098,2212,4.389,2230,1.929,2238,3.416,2239,5.934,2240,2.098,2241,2.098,2246,2.098,2250,3.416,2254,3.416,2255,2.098,2256,4.32,2257,4.32,2258,3.416,2259,2.098,2260,2.098,2261,2.098,2262,3.416,2263,4.32,2264,2.098,2265,2.098,2266,2.098,2267,2.098,2268,2.098,2269,2.098,2270,3.416,2271,2.098,2272,2.098,2273,2.098,2289,1.929,2290,2.098,2291,2.098,2292,1.929,2293,1.929,2294,1.929,2311,1.929,2312,3.834,2313,2.355,2314,2.355,2315,3.834,2316,3.416,2317,3.834,2318,3.834,2319,2.355,2320,3.834,2321,3.834,2322,2.355,2323,2.355,2324,3.834,2325,2.355,2326,2.355,2327,3.834,2328,2.355,2329,5.588,2330,2.355,2331,1.702,2332,2.355,2333,2.355,2334,2.355,2335,2.355,2336,1.929,2337,2.355,2338,2.098,2339,3.834,2340,2.098,2341,2.355,2342,2.355,2343,2.098,2344,2.355,2345,2.355,2346,3.416,2347,2.098,2348,2.098,2349,3.834,2350,2.355,2351,2.355,2352,2.355]],["tags/81",[]],["title/82",[958,3.172,1044,4.155]],["content/82",[27,2.789,335,2.789,912,4.246,1044,5.752,1983,5.43,2212,4.553,2353,7.516]],["tags/82",[]],["title/83",[58,1.396,62,0.725,63,1.426,69,1.241,92,1.218]],["content/83",[5,2.438,2212,4.727]],["tags/83",[]],["title/75",[1,1.028,241,2.413,2354,3.381,2355,3.381]],["content/75",[]],["tags/75",[256,0.692,257,1.397]],["title/76",[307,1.741,2354,3.841,2355,3.841]],["content/76",[1,1.183,3,1.822,8,1.083,19,2.318,23,1.431,26,2.287,46,1.163,47,1.051,61,2.275,79,1.273,138,1.101,210,3.217,241,1.805,243,2.753,268,2.121,273,2.121,287,2.529,306,4.232,307,1.146,311,1.22,312,1.302,313,2.773,314,2.751,315,3.074,316,5.675,317,2.231,318,2.751,319,2.529,320,2.685,321,3.892,322,4.433,323,4.744,324,3.801,325,6.326,326,5.327,327,3.935,328,4.433,329,4.185,330,4.185,331,4.185,332,4.433,333,4.433,334,2.701,335,2.15,336,3.726,337,2.287,338,2.529,339,2.121,340,4.699,341,1.745,342,2.364,343,2.751,344,2.751,345,2.777,346,2.027,347,2.529,348,3.119,356,2.231,421,1.332,453,2.751,496,2.231,499,5.16,524,2.529,537,2.751,784,3.26,786,3.119,787,2.231,852,4.744,1646,2.529,2356,4.752,2357,3.088,2358,3.088,2359,3.088,2360,3.088,2361,3.088,2362,3.088,2363,3.088]],["tags/76",[]],["title/77",[58,1.396,62,0.725,63,1.426,69,1.241,92,1.218]],["content/77",[1,1.899,5,2.384,241,4.458,2354,6.248,2355,6.248]],["tags/77",[]],["title/149",[8,0.623,46,0.815,47,0.737,1142,1.822,2364,1.822,2365,2.018]],["content/149",[8,1.006,18,2.379,32,3.887,41,1.681,44,2.944,46,1.73,47,1.564,49,3.04,50,2.218,71,3.448,75,3.04,100,3.855,105,2.944,118,2.493,155,2.625,157,2.761,166,2.557,243,2.557,256,2.375,274,3.259,293,1.957,412,4.319,580,3.36,607,2.944,822,2.944,1057,3.695,1064,4.282,1103,4.319,1142,3.867,1329,3.695,1702,4.793,1820,4.793,1921,5.41,2331,3.887,2364,2.944,2365,4.282,2366,4.793,2367,5.38,2368,5.38,2369,5.38,2370,5.38]],["tags/149",[547,0.678,1103,0.612,2364,0.612]],["title/150",[172,2.455,335,2.015]],["content/150",[1,1.325,3,1.03,8,0.995,13,2.668,16,3.111,23,2.467,26,2.102,27,1.976,35,2.407,46,2.224,47,2.01,54,2.826,91,1.661,116,3.225,210,2.832,246,3.352,260,3.225,262,3.425,307,1.976,312,2.245,315,2.826,327,2.826,335,3.099,337,2.772,348,3.494,607,2.913,620,3.847,683,2.351,778,1.281,1142,2.913,1411,6.997,1803,6.432,1983,3.847,2365,3.225,2371,4.075,2372,5.324,2373,6.432,2374,5.324]],["tags/150",[]],["title/151",[41,1.152,157,1.29,307,1.368,320,2.083,2375,3.687]],["content/151",[3,1.9,18,2.144,35,1.633,41,1.672,44,2.927,46,1.559,47,0.799,49,2.041,50,2.626,55,2.112,79,1.489,91,0.855,100,1.558,117,2.185,118,3.263,148,2.463,153,2.255,155,3.107,156,2.958,157,2.228,163,2.626,166,1.717,218,4.375,284,1.489,307,1.985,421,1.558,452,4.094,584,2.839,615,2.481,648,2.188,683,1.595,745,3.218,788,1.762,817,2.041,838,1.762,964,1.917,1103,4.113,1475,2.481,1690,2.958,1803,2.958,1843,3.218,2022,3.218,2165,5.087,2227,2.765,2364,3.853,2365,2.188,2376,3.612,2377,3.612,2378,3.612,2379,2.765,2380,4.602,2381,2.765,2382,4.836,2383,3.864,2384,2.61,2385,2.765,2386,2.765,2387,2.765,2388,2.765,2389,2.765,2390,2.765,2391,2.765,2392,2.765,2393,2.958,2394,2.958,2395,2.958,2396,2.958,2397,4.381,2398,2.958,2399,2.958,2400,2.958,2401,2.958]],["tags/151",[]],["title/152",[55,1.315,91,0.788,155,1.625,580,1.583,819,2.186,1103,1.822]],["content/152",[19,3.463,26,2.803,35,3.21,90,3.659,100,3.062,102,2.634,284,2.927,770,2.927,799,5.129,803,4.469,958,4.148,1103,3.884,1276,6.324,1904,4.658,2364,3.884]],["tags/152",[]],["title/153",[91,0.977,1102,2.332,2402,4.128,2403,3.678]],["content/153",[3,1.817,90,3.584,91,1.645,102,2.581,683,3.07,1102,3.929,1103,3.805,1135,5.024,2364,3.805,2382,4.776,2403,6.195,2404,6.954,2405,5.322,2406,5.322]],["tags/153",[]],["title/154",[91,1.285,155,2.648]],["content/154",[3,1.844,8,1.117,18,2.011,44,2.302,55,2.359,79,1.735,91,0.995,100,3.262,102,1.561,132,2.052,148,1.627,155,3.689,163,1.735,166,4.217,167,3.445,194,3.22,256,1.857,274,3.619,303,3.039,313,1.661,324,2.458,384,2.052,421,1.814,446,2.458,558,2.458,573,3.445,580,1.999,584,2.233,611,3.22,624,3.761,626,3.748,629,3.445,723,4.688,799,3.039,840,3.748,958,2.458,1050,3.445,1064,2.548,1103,2.302,1475,2.889,1489,2.648,1490,2.889,1590,4.572,1835,3.748,1904,3.92,2123,4.893,2227,3.22,2331,3.039,2364,3.801,2380,3.039,2382,2.889,2383,3.039,2384,4.316,2407,4.207,2408,4.207,2409,5.974,2410,5.019,2411,3.748,2412,5.317,2413,4.207,2414,3.22,2415,3.22]],["tags/154",[]],["title/155",[91,0.872,100,1.59,274,2.233,1064,2.233,2416,3.687]],["content/155",[3,1.805,8,1.187,18,2.137,50,2.618,81,5.676,91,1.502,100,2.738,148,2.455,166,3.018,274,3.846,284,2.618,308,3.997,328,4.859,723,3.587,1064,3.846,1103,3.474,2410,4.587,2417,5.656,2418,6.349,2419,4.859,2420,4.859,2421,4.859,2422,4.859,2423,4.859,2424,4.859,2425,4.859]],["tags/155",[]],["title/156",[26,1.852,284,1.934,944,3.841]],["content/156",[3,1.92,44,1.405,46,1.258,47,0.568,50,1.059,65,2.698,81,1.856,100,1.774,117,1.764,118,2.383,148,2.486,153,1.734,155,2.006,163,2.12,166,3.763,218,2.824,274,1.556,384,1.253,387,1.856,584,2.182,624,4.048,723,3.875,817,1.451,838,1.253,982,2.104,1102,2.323,1103,2.813,1135,1.856,1183,3.237,1475,1.764,1489,1.617,1490,1.764,1904,2.698,2165,3.715,2364,3.753,2379,1.966,2380,3.715,2381,1.966,2382,3.531,2383,2.971,2384,1.856,2385,1.966,2386,1.966,2387,1.966,2388,1.966,2389,1.966,2390,1.966,2391,1.966,2392,1.966,2393,2.104,2394,2.104,2395,2.104,2396,4.211,2397,5.618,2398,4.211,2399,4.211,2400,4.211,2401,4.211,2405,1.966,2406,1.966,2410,2.971,2411,2.288,2412,3.147,2414,1.966,2415,1.966,2419,1.966,2420,1.966,2421,1.966,2422,1.966,2423,1.966,2424,1.966,2425,1.966,2426,2.569,2427,2.104,2428,2.288,2429,2.288,2430,2.288,2431,2.288,2432,2.288,2433,2.288,2434,2.288,2435,5.141,2436,5.141,2437,5.141,2438,5.141,2439,5.141,2440,5.141,2441,5.141,2442,5.141,2443,5.141,2444,4.581,2445,4.581,2446,4.211,2447,2.288,2448,2.288]],["tags/156",[]],["title/157",[91,0.977,157,1.444,834,2.836,2365,2.501]],["content/157",[18,2.458,19,3.562,26,2.883,62,1.436,138,2.604,157,2.554,452,5.588,475,5.98,2227,5.588,2449,5.588,2450,7.301]],["tags/157",[]],["title/158",[91,1.285,2451,4.836]],["content/158",[3,1.84,8,1.158,51,2.046,91,1.466,117,2.125,153,2.612,157,2.167,307,2.299,393,4.476,577,3.105,648,3.753,1047,6.337,2289,5.074,2292,5.074,2293,5.074,2294,5.074,2346,6.893,2347,5.519,2348,5.519,2365,3.753,2371,4.741,2449,4.741,2451,7.516,2452,6.195,2453,6.195]],["tags/158",[]],["title/159",[91,0.977,157,1.444,246,2.599,2364,2.259]],["content/159",[3,1.93,44,1.289,46,1.368,47,0.848,50,1.581,51,0.778,81,1.702,91,0.557,100,2.091,117,1.917,118,2.247,148,2.688,153,1.617,155,3.001,157,0.824,163,1.999,166,3.134,172,1.065,218,3.33,222,1.803,263,1.149,280,1.702,384,1.149,531,2.098,547,1.427,580,1.12,581,1.483,584,2.035,624,1.483,723,3.725,770,0.971,806,1.483,817,1.331,838,1.149,1015,2.653,1064,1.427,1100,1.803,1102,2.739,1103,2.653,1106,1.331,1135,1.702,1142,2.098,1161,1.702,1175,1.803,1180,2.516,1183,1.483,1256,2.414,1281,2.935,1282,1.702,1283,1.702,1329,3.33,1475,1.618,1482,1.803,1489,3.052,1490,1.618,1552,1.929,1681,1.618,1782,1.929,1904,3.667,2165,3.503,2168,2.098,2364,2.098,2365,1.427,2371,1.803,2379,1.803,2380,3.503,2381,1.803,2382,3.33,2383,2.77,2384,1.702,2385,1.803,2386,1.803,2387,1.803,2388,1.803,2389,1.803,2390,1.803,2391,1.803,2392,1.803,2405,1.803,2406,1.803,2410,2.77,2412,2.935,2414,1.803,2415,1.803,2419,1.803,2420,1.803,2421,1.803,2422,1.803,2423,2.935,2424,1.803,2425,1.803,2427,1.929,2446,1.929,2449,3.711,2454,3.416,2455,3.416,2456,4.979,2457,2.355,2458,2.098,2459,2.355,2460,2.355,2461,4.32,2462,4.32,2463,2.098,2464,2.098,2465,2.098,2466,2.098,2467,2.098,2468,2.098,2469,2.098,2470,2.098,2471,2.098,2472,2.098,2473,2.098,2474,2.098,2475,2.098,2476,2.098,2477,2.098,2478,2.098,2479,2.098,2480,2.098,2481,2.098,2482,2.098,2483,2.355]],["tags/159",[]],["title/160",[62,0.549,91,0.661,100,1.204,229,2.017,274,1.691,646,1.439,755,1.832,2331,2.017]],["content/160",[3,1.93,23,0.81,26,0.69,44,0.956,46,1.134,47,0.661,50,2.146,62,0.344,65,1.961,81,1.263,88,1.059,91,0.414,100,1.688,117,2.193,118,1.814,148,2.756,153,1.953,155,2.539,163,1.614,166,3.628,172,0.79,218,2.688,222,1.337,274,1.81,285,0.69,308,1.1,384,0.853,531,2.142,581,1.1,584,1.586,624,3.277,646,0.901,723,3.425,755,1.147,799,1.263,817,0.987,838,0.853,855,1.337,923,1.263,1015,2.142,1017,1.059,1100,1.337,1102,2.211,1103,2.142,1106,0.987,1135,1.263,1137,1.147,1142,1.635,1161,2.159,1175,1.337,1180,1.961,1183,2.464,1256,1.881,1281,2.287,1282,1.263,1283,1.263,1284,1.557,1329,3.182,1475,1.2,1482,1.337,1489,2.464,1490,1.2,1552,1.431,1681,1.2,1782,1.431,1904,3.416,2165,2.828,2331,1.263,2364,2.848,2365,2.371,2371,1.337,2379,1.337,2380,2.828,2381,1.337,2382,2.688,2383,2.159,2384,1.263,2385,1.337,2386,1.337,2387,1.337,2388,1.337,2389,1.337,2390,1.337,2391,1.337,2392,1.337,2393,1.431,2394,1.431,2395,1.431,2396,2.447,2397,3.794,2398,2.447,2399,2.447,2400,2.447,2401,2.447,2405,1.337,2406,1.337,2410,2.159,2412,2.287,2414,1.337,2415,1.337,2419,1.337,2420,1.337,2421,1.337,2422,1.337,2423,2.287,2424,1.337,2425,1.337,2427,1.431,2428,1.557,2429,1.557,2430,1.557,2431,1.557,2432,1.557,2433,1.557,2434,1.557,2444,2.662,2445,2.662,2446,3.794,2447,1.557,2448,1.557,2449,2.996,2454,2.662,2455,2.662,2456,4.127,2458,1.557,2461,3.487,2462,4.127,2463,1.557,2464,1.557,2465,1.557,2466,1.557,2467,1.557,2468,1.557,2469,1.557,2470,1.557,2471,1.557,2472,1.557,2473,1.557,2474,1.557,2475,1.557,2476,1.557,2477,1.557,2478,1.557,2479,1.557,2480,1.557,2481,1.557,2482,1.557,2484,1.747,2485,2.988,2486,1.747,2487,1.747,2488,1.747,2489,1.747,2490,2.988,2491,1.747,2492,3.914,2493,1.747,2494,1.747,2495,1.747,2496,2.988,2497,2.988,2498,2.988,2499,2.988,2500,2.988,2501,1.747]],["tags/160",[]],["title/161",[58,1.396,62,0.725,63,1.426,69,1.241,92,1.218]],["content/161",[5,2.349,8,1.405,46,1.84,47,1.663,1142,4.112,2364,4.112,2365,4.553]],["tags/161",[]],["title/84",[778,1.306,2253,4.446]],["content/84",[30,1.886,37,2.386,47,1.538,62,1.368,75,3.929,138,2.48,256,3.07,284,2.867,294,4.776,346,4.563,449,6.195,775,5.695,778,1.673,812,3.69,822,3.805,912,3.929,1209,5.322,2028,5.695]],["tags/84",[778,0.377,2502,1.568]],["title/85",[782,5.74]],["content/85",[5,1.664,8,0.995,13,2.668,21,3.225,22,2.668,27,1.976,30,1.904,33,3.847,35,2.407,37,2.977,47,1.178,51,2.319,54,3.726,100,2.296,102,1.976,103,2.148,165,3.847,210,2.148,250,4.361,258,2.826,260,4.252,267,3.847,298,1.976,302,3.336,303,3.847,335,3.099,349,2.668,350,2.148,501,4.743,544,3.352,744,4.743,774,4.297,778,1.89,783,4.075,784,3.518,785,4.743,786,3.494,787,3.847,823,3.352,824,4.361,877,4.075,1940,4.361,1993,4.743,2503,5.324,2504,5.324,2505,5.324]],["tags/85",[]],["title/86",[26,2.544]],["content/86",[]],["tags/86",[]],["title/87",[30,1.272,172,2.121,243,2.229]],["content/87",[3,1.491,27,2.285,30,2.462,37,2.113,41,1.924,91,1.457,311,2.432,334,2.154,337,2.432,410,5.043,588,4.753,774,4.825,778,1.482,779,3.876,788,3.004,790,5.486,797,3.876,958,3.599,1880,5.043,2506,5.043,2507,6.158,2508,6.158,2509,6.158,2510,6.158,2511,6.158,2512,6.158,2513,6.158]],["tags/87",[]],["title/88",[37,1.609,320,2.65,802,2.741]],["content/88",[3,1.91,37,2.586,311,2.347,315,3.154,350,2.398,384,4.038,674,4.082,784,2.979,800,4.549,802,3.473,803,3.741,804,4.867,805,2.754,806,4.745,810,5.769,812,3.154,813,6.715,814,4.867,816,3.358,818,5.295,2514,5.943]],["tags/88",[]],["title/89",[37,1.609,334,1.64,819,3.078]],["content/89",[8,1.074,30,1.558,37,3.05,48,2.436,103,2.317,116,3.479,263,2.802,305,3.142,307,2.131,339,5.065,350,2.317,401,3.769,402,3.944,729,3.944,760,3.944,774,4.703,788,3.974,802,4.76,806,5.128,808,6.04,823,5.128,861,5.116,964,3.048,1890,4.395,2515,5.743,2516,5.743,2517,5.743,2518,5.743,2519,5.743,2520,5.116,2521,5.743]],["tags/89",[]],["title/90",[334,1.444,812,2.191,834,2.836,2506,3.381]],["content/90",[8,0.861,22,2.308,27,1.709,35,4.034,37,2.183,48,2.102,62,1.252,90,2.373,91,1.09,92,1.521,102,1.709,103,1.858,116,2.789,138,1.642,210,1.858,298,2.362,302,2.189,327,2.444,334,1.61,335,2.362,336,2.444,337,1.818,339,3.163,345,3.719,349,2.308,350,2.568,410,5.213,683,2.033,770,1.899,778,2.055,784,2.308,803,2.899,808,3.771,812,3.378,816,3.596,820,5.213,821,3.719,823,2.899,849,3.524,859,2.899,923,3.327,1050,3.771,1199,2.899,1789,4.102,1866,3.524,1884,3.524,1894,3.771,2060,4.102,2095,4.102,2230,3.771,2311,3.771,2336,3.771,2343,4.102,2506,5.213,2520,4.102,2522,4.605,2523,4.605,2524,4.605,2525,4.605,2526,4.102,2527,4.605,2528,6.364,2529,4.605,2530,4.102,2531,4.605,2532,4.605,2533,3.771]],["tags/90",[]],["title/91",[58,1.396,62,0.725,63,1.426,69,1.241,92,1.218]],["content/91",[5,2.42,778,1.864,2253,6.342]],["tags/91",[]],["title/100",[30,0.824,212,2.325,298,1.127,628,2.194,778,1.129,1892,1.912]],["content/100",[1,1.708,8,1.283,30,2.234,41,2.144,47,1.518,51,2.266,248,4.319,256,3.029,298,2.546,346,4.502,775,5.619,778,1.982,805,3.179,1892,4.319,2534,6.86,2535,6.86,2536,6.86,2537,6.86]],["tags/100",[778,0.63]],["title/101",[3,0.713,298,1.368,778,1.307,1892,2.321]],["content/101",[3,0.867,8,0.838,19,2.187,23,2.078,30,1.694,35,3.252,37,2.143,41,2.247,47,1.874,48,2.375,51,2.064,67,2.247,91,1.061,103,3.299,244,2.311,248,2.822,252,2.822,284,2.965,285,1.77,298,2.319,302,2.131,308,2.822,311,1.77,327,2.379,334,2.86,345,2.62,350,3.299,421,1.934,580,2.969,607,2.453,770,2.576,778,2.167,786,4.1,788,2.187,789,3.898,803,3.933,805,2.895,809,3.431,812,2.379,968,2.822,1057,3.079,1209,4.782,1884,3.431,1892,2.822,1918,3.431,2121,3.994,2338,3.994,2538,4.483,2539,4.483,2540,4.483,2541,3.994,2542,3.994,2543,4.483]],["tags/101",[]],["title/102",[3,0.713,298,1.368,778,1.307,1892,2.321]],["content/102",[8,1.322,26,2.125,27,1.997,30,2.141,35,2.433,47,1.855,48,2.876,50,2.914,79,2.218,117,1.846,252,3.387,284,2.914,298,2.93,308,4.45,311,2.791,334,2.472,346,3.531,413,2.493,458,3.887,580,3.36,607,3.867,621,4.406,687,4.793,778,2.096,797,3.387,812,2.855,903,4.406,912,3.04,948,3.887,964,4.19,1860,4.406,1892,3.387,1976,4.406,2417,4.793,2544,5.38,2545,5.38]],["tags/102",[]],["title/103",[26,2.544]],["content/103",[1,1.319,35,3.163,46,1.712,47,1.548,51,2.311,95,3.638,103,3.16,118,2.454,166,2.517,210,2.137,298,2.596,315,2.811,327,3.713,329,3.827,345,3.095,350,3.16,412,2.898,413,2.454,439,4.338,607,2.898,703,3.827,778,2.243,789,4.176,803,3.334,823,3.334,848,2.992,872,3.827,958,3.095,1121,3.827,1404,4.338,1938,4.338,2218,4.719,2541,4.719,2542,4.719,2546,6.996,2547,5.296,2548,5.296,2549,5.296,2550,5.296,2551,5.296,2552,5.296,2553,5.296]],["tags/103",[]],["title/104",[58,1.396,62,0.725,63,1.426,69,1.241,92,1.218]],["content/104",[5,2.349,212,5.752,298,2.789,628,5.43,778,2.091,1892,4.731]],["tags/104",[]],["title/92",[311,1.852,698,3.221,957,2.841]],["content/92",[]],["tags/92",[911,1.077,957,0.95]],["title/93",[936,4.655]],["content/93",[3,1.716,9,4.8,30,1.701,40,3.431,60,3.799,62,1.233,106,3.948,112,5.116,117,2.911,194,4.8,210,2.53,285,2.476,302,2.981,306,3.328,340,5.633,558,3.665,698,4.307,948,4.531,968,3.948,1192,5.136,1268,5.587,1646,5.136,2554,7.796,2555,6.271,2556,5.587,2557,6.271]],["tags/93",[]],["title/94",[30,1.472,210,2.19]],["content/94",[91,1.778,117,2.579,305,4.112,337,2.968,910,6.696,911,5.162,912,4.246]],["tags/94",[]],["title/95",[285,1.852,311,1.852,957,2.841]],["content/95",[3,1.877,27,2.463,48,2.667,71,3.238,91,1.571,341,4.561,558,3.879,698,5.545,773,5.08,906,4.559,974,5.913,981,5.08,2558,6.637,2559,6.637]],["tags/95",[]],["title/96",[285,1.852,311,1.852,911,3.221]],["content/96",[3,1.832,27,2.371,48,2.826,71,3.117,91,1.512,117,2.192,305,4.315,312,2.694,558,3.733,788,3.117,873,4.89,906,4.388,911,4.388,912,4.455,914,5.692,1590,4.89,2123,5.233,2560,6.389,2561,6.389,2562,6.389,2563,6.389]],["tags/96",[]],["title/97",[61,1.64,157,1.64,2564,4.69]],["content/97",[3,1.868,22,2.499,48,1.647,62,1.322,69,1.678,71,2.433,92,1.647,102,1.851,117,3.16,132,3.278,157,2.658,293,1.814,330,3.603,337,2.654,357,4.084,398,2.139,413,2.311,417,3.139,597,4.23,683,2.202,772,4.442,822,2.728,833,4.442,996,4.855,1017,4.071,1106,3.796,1192,4.084,1329,4.615,1859,4.084,2297,5.987,2556,4.442,2565,4.986,2566,6.72,2567,6.72,2568,6.72,2569,6.72,2570,4.986]],["tags/97",[]],["title/98",[590,4.931]],["content/98",[244,3.991,698,5.318,957,4.691]],["tags/98",[]],["title/99",[58,1.396,62,0.725,63,1.426,69,1.241,92,1.218]],["content/99",[5,2.402,311,3.035,698,5.278,957,4.656]],["tags/99",[]],["title/105",[8,0.568,592,1.912,966,2.325,1049,2.086,1659,2.194,2571,2.488,2572,2.325]],["content/105",[3,1.898,8,0.783,20,2.222,33,1.899,42,2.152,46,1.592,47,0.926,50,1.727,73,1.485,75,1.485,79,1.084,91,0.991,92,0.868,101,1.654,117,1.437,144,1.805,148,2.679,153,1.766,155,2.043,157,1.826,163,1.084,200,1.805,234,1.899,255,2.748,276,1.805,280,1.899,290,3.205,331,1.899,364,3.995,412,2.291,422,2.876,426,2.341,439,2.152,445,2.011,446,3.051,535,1.536,552,2.011,561,3.426,581,2.636,584,1.395,592,5.295,597,1.654,605,2.011,692,3.205,770,1.084,773,2.011,814,2.152,817,1.485,835,1.805,873,3.205,966,4.557,968,1.654,1049,3.585,1057,1.805,1092,2.152,1126,2.341,1195,2.341,1199,1.654,1256,1.654,1267,5.326,1405,2.011,1489,1.654,1659,5.006,1681,1.805,1688,3.205,1690,2.152,1712,3.731,1737,2.341,1738,2.341,1740,3.731,1741,2.341,1742,2.341,1788,1.805,1869,2.152,1891,2.152,1908,2.341,1976,2.152,1985,2.152,2019,2.152,2336,2.152,2530,2.341,2571,2.152,2572,2.011,2573,2.628,2574,2.628,2575,5.954,2576,2.628,2577,2.628,2578,2.628,2579,2.628,2580,4.188,2581,2.628,2582,5.22,2583,4.188,2584,4.188,2585,2.628,2586,2.628,2587,2.628,2588,4.188,2589,4.188,2590,2.628,2591,2.628,2592,2.628,2593,2.628,2594,2.628,2595,2.628,2596,2.628,2597,4.188,2598,4.188,2599,2.628,2600,4.188,2601,2.628,2602,2.628,2603,2.628,2604,2.628,2605,4.188,2606,2.628,2607,2.628,2608,2.628,2609,2.628,2610,2.628,2611,2.628,2612,2.628,2613,2.628,2614,2.628,2615,2.628,2616,2.628]],["tags/105",[547,0.527,1659,0.629,2572,0.666,2617,0.87]],["title/106",[58,1.396,62,0.725,63,1.426,69,1.241,92,1.218]],["content/106",[5,2.332,8,1.395,592,4.697,966,5.71,1049,5.124,1659,5.391,2571,6.111,2572,5.71]],["tags/106",[]],["title/115",[210,1.344,293,1.212,337,1.315,902,2.288,2618,2.728,2619,2.728]],["content/115",[8,0.81,22,2.171,23,2.007,30,1.654,51,1.431,72,4.632,79,1.786,102,1.608,158,5.781,189,3.859,210,2.848,266,3.129,293,3.131,305,2.37,315,4.066,329,5.1,333,3.315,335,1.608,336,3.746,337,3.575,394,2.975,412,3.862,422,2.975,430,2.624,471,5.433,485,4.995,491,3.548,496,3.129,567,4.995,577,3.057,579,3.548,588,2.447,609,3.129,623,3.548,805,2.007,859,4.823,872,3.129,902,4.848,929,3.315,1092,3.548,1270,3.859,1848,3.548,1890,3.315,1919,3.315,2311,3.548,2618,5.781,2619,6.614,2620,4.331,2621,4.331,2622,7.058,2623,4.331,2624,4.331,2625,4.331,2626,4.331,2627,4.331,2628,4.331,2629,4.331,2630,4.331,2631,4.331]],["tags/115",[210,0.452,256,0.494,337,0.442]],["title/116",[58,1.396,62,0.725,63,1.426,69,1.241,92,1.218]],["content/116",[5,2.349,210,3.032,293,2.734,337,2.968,902,5.162,2618,6.156,2619,6.156]],["tags/116",[]],["title/107",[8,0.877,398,1.493,546,2.841]],["content/107",[]],["tags/107",[94,0.519,103,0.452,350,0.452]],["title/108",[350,2.599]],["content/108",[]],["tags/108",[]],["title/109",[816,3.64]],["content/109",[3,1.48,8,1.138,13,3.05,22,3.05,40,3.329,62,1.197,94,3.545,102,2.258,124,4.179,138,2.17,244,3.136,271,4.179,276,5.254,285,2.403,298,2.258,302,2.892,421,2.624,482,6.815,648,3.686,812,3.229,816,4.322,1102,3.438,1863,4.396,2193,5.421,2533,4.983,2632,5.421,2633,8.78,2634,6.084,2635,6.084,2636,6.084,2637,6.084]],["tags/109",[]],["title/110",[821,3.765]],["content/110",[3,1.123,8,1.388,22,2.025,40,2.211,62,1.336,71,1.971,87,5.563,94,3.148,105,2.211,115,5.199,138,2.648,140,3.6,176,2.682,244,2.083,274,3.516,276,2.775,280,2.919,298,1.5,300,4.194,312,1.704,350,1.63,395,3.6,398,2.162,400,5.171,412,2.211,428,3.6,430,3.516,531,3.717,553,2.919,567,3.309,573,3.309,581,4.276,592,2.544,594,4.754,614,2.544,711,4.195,779,2.544,830,3.309,864,5.199,1283,2.919,1788,2.775,1865,2.919,1874,4.665,1880,3.309,1895,4.754,1919,3.092,2161,3.6,2366,3.6,2373,4.754,2632,7.514,2638,5.171,2639,4.04,2640,4.04,2641,4.754,2642,4.04,2643,4.04,2644,4.04,2645,4.04,2646,5.804,2647,4.04,2648,5.804,2649,5.171,2650,4.04,2651,3.6,2652,6.615,2653,4.04,2654,4.04,2655,4.04,2656,4.04,2657,4.04,2658,4.04,2659,3.6,2660,4.04]],["tags/110",[]],["title/111",[103,2.599]],["content/111",[]],["tags/111",[]],["title/112",[335,1.741,821,2.741,2661,3.59]],["content/112",[3,1.524,7,2.379,8,1.003,20,2.846,27,1.99,39,2.379,54,2.846,59,5.686,62,0.713,67,1.817,69,1.22,71,1.768,79,1.495,87,4.392,89,2.969,94,2.485,138,2.516,176,1.431,210,2.163,218,2.49,243,1.723,254,2.49,271,2.49,276,2.49,280,2.619,296,2.774,298,1.345,300,3.875,302,1.723,311,1.431,313,2.118,324,3.134,335,1.345,349,2.688,380,1.768,398,1.707,430,3.249,445,2.774,448,4.392,459,4.778,547,2.196,561,2.379,563,2.774,566,4.778,572,2.379,580,1.723,581,4.018,592,2.282,594,2.969,627,3.229,648,2.196,671,3.229,711,2.048,714,1.983,746,2.048,819,2.379,821,3.134,835,3.683,864,4.885,923,2.619,929,4.104,1788,3.683,1865,2.619,1874,3.683,1918,2.774,1921,2.774,2050,5.686,2316,3.229,2340,3.229,2373,2.969,2526,6.284,2533,4.392,2638,3.229,2641,2.969,2649,3.229,2651,3.229,2652,7.265,2661,6.242,2662,3.625,2663,3.625,2664,5.363,2665,3.625,2666,3.625,2667,3.625,2668,3.625,2669,3.625,2670,3.625,2671,3.625,2672,3.625,2673,3.625,2674,3.625,2675,3.625,2676,3.625,2677,3.229,2678,3.625,2679,3.625,2680,3.625,2681,3.625,2682,3.625]],["tags/112",[]],["title/113",[821,2.413,2661,3.16,2683,3.678,2684,3.678]],["content/113",[3,1.463,94,3.846,103,2.412,138,2.132,165,4.319,243,2.841,276,4.106,296,4.575,335,3.238,380,2.916,413,2.77,444,5.326,629,4.896,673,4.896,736,6.74,738,3.763,802,4.421,821,4.421,1904,3.923,1983,4.319,2118,4.896,2641,4.896,2659,5.326,2661,4.575,2677,5.326,2683,5.326,2684,5.326,2685,5.978,2686,5.978,2687,5.978,2688,5.978,2689,5.978,2690,5.978]],["tags/113",[]],["title/114",[58,1.396,62,0.725,63,1.426,69,1.241,92,1.218]],["content/114",[5,2.402,8,1.437,398,2.446,546,4.656]],["tags/114",[]]],"invertedIndex":[["",{"_index":3,"title":{"101":{},"102":{},"121":{},"142":{},"146":{}},"content":{"1":{},"13":{},"14":{},"20":{},"21":{},"22":{},"24":{},"33":{},"34":{},"39":{},"40":{},"41":{},"46":{},"53":{},"55":{},"60":{},"64":{},"65":{},"66":{},"67":{},"76":{},"79":{},"80":{},"81":{},"87":{},"88":{},"93":{},"95":{},"96":{},"97":{},"101":{},"105":{},"109":{},"110":{},"112":{},"113":{},"119":{},"120":{},"121":{},"122":{},"126":{},"127":{},"128":{},"130":{},"131":{},"132":{},"133":{},"135":{},"136":{},"137":{},"138":{},"150":{},"151":{},"153":{},"154":{},"155":{},"156":{},"158":{},"159":{},"160":{}},"tags":{}}],["0",{"_index":1256,"title":{},"content":{"80":{},"105":{},"133":{},"136":{},"137":{},"138":{},"159":{},"160":{}},"tags":{}}],["0.0.1",{"_index":2039,"title":{},"content":{"55":{}},"tags":{}}],["0.3",{"_index":2210,"title":{},"content":{"122":{}},"tags":{}}],["0.60.0",{"_index":2514,"title":{},"content":{"88":{}},"tags":{}}],["0.72.6",{"_index":2552,"title":{},"content":{"103":{}},"tags":{}}],["0.8",{"_index":152,"title":{},"content":{"1":{}},"tags":{}}],["000",{"_index":231,"title":{},"content":{"1":{}},"tags":{}}],["012aaaa3",{"_index":2509,"title":{},"content":{"87":{}},"tags":{}}],["1",{"_index":172,"title":{"19":{},"87":{},"150":{}},"content":{"1":{},"6":{},"34":{},"73":{},"80":{},"81":{},"120":{},"121":{},"122":{},"132":{},"133":{},"135":{},"136":{},"137":{},"159":{},"160":{}},"tags":{}}],["1,};const",{"_index":2205,"title":{},"content":{"122":{}},"tags":{}}],["1.0",{"_index":216,"title":{},"content":{"1":{}},"tags":{}}],["1.0.4",{"_index":478,"title":{},"content":{"41":{}},"tags":{}}],["1.1.0",{"_index":477,"title":{},"content":{"41":{}},"tags":{}}],["1.18.2",{"_index":2548,"title":{},"content":{"103":{}},"tags":{}}],["1.2",{"_index":150,"title":{},"content":{"1":{}},"tags":{}}],["1.4.3",{"_index":2549,"title":{},"content":{"103":{}},"tags":{}}],["1.png",{"_index":1422,"title":{},"content":{"136":{}},"tags":{}}],["10",{"_index":226,"title":{},"content":{"1":{},"21":{},"73":{}},"tags":{}}],["10.1.0",{"_index":483,"title":{},"content":{"41":{}},"tags":{}}],["100",{"_index":234,"title":{},"content":{"1":{},"66":{},"105":{},"122":{},"133":{}},"tags":{}}],["10000",{"_index":693,"title":{},"content":{"33":{}},"tags":{}}],["11",{"_index":141,"title":{},"content":{"1":{},"65":{}},"tags":{}}],["11.0",{"_index":467,"title":{},"content":{"41":{}},"tags":{}}],["11.4.0",{"_index":2550,"title":{},"content":{"103":{}},"tags":{}}],["12",{"_index":1319,"title":{},"content":{"71":{},"135":{},"136":{}},"tags":{}}],["120",{"_index":1565,"title":{},"content":{"136":{}},"tags":{}}],["13",{"_index":2178,"title":{},"content":{"122":{}},"tags":{}}],["14",{"_index":1420,"title":{},"content":{"55":{},"136":{}},"tags":{}}],["14.3.0",{"_index":2551,"title":{},"content":{"103":{}},"tags":{}}],["140",{"_index":2209,"title":{},"content":{"122":{}},"tags":{}}],["15",{"_index":1633,"title":{},"content":{"136":{}},"tags":{}}],["16",{"_index":1260,"title":{},"content":{"133":{},"135":{}},"tags":{}}],["16.2",{"_index":1896,"title":{},"content":{"65":{}},"tags":{}}],["169",{"_index":1265,"title":{},"content":{"133":{}},"tags":{}}],["17",{"_index":1575,"title":{},"content":{"136":{}},"tags":{}}],["180",{"_index":1924,"title":{},"content":{"66":{}},"tags":{}}],["189",{"_index":669,"title":{},"content":{"30":{}},"tags":{}}],["2",{"_index":320,"title":{"20":{},"88":{},"151":{}},"content":{"6":{},"40":{},"41":{},"66":{},"73":{},"76":{},"122":{},"132":{}},"tags":{}}],["2.0",{"_index":2357,"title":{},"content":{"76":{}},"tags":{}}],["2.png",{"_index":1424,"title":{},"content":{"136":{}},"tags":{}}],["20",{"_index":2118,"title":{},"content":{"113":{},"120":{},"122":{}},"tags":{}}],["24",{"_index":1784,"title":{},"content":{"137":{}},"tags":{}}],["257",{"_index":1906,"title":{},"content":{"66":{}},"tags":{}}],["269",{"_index":1266,"title":{},"content":{"133":{}},"tags":{}}],["2704",{"_index":1898,"title":{},"content":{"65":{}},"tags":{}}],["2f842489f07a",{"_index":2513,"title":{},"content":{"87":{}},"tags":{}}],["3",{"_index":819,"title":{"21":{},"89":{},"152":{}},"content":{"66":{},"73":{},"112":{},"136":{}},"tags":{}}],["3.0.0",{"_index":811,"title":{},"content":{"20":{}},"tags":{}}],["3.1.5",{"_index":2219,"title":{},"content":{"79":{}},"tags":{}}],["3.png",{"_index":1426,"title":{},"content":{"136":{}},"tags":{}}],["32",{"_index":1578,"title":{},"content":{"136":{}},"tags":{}}],["38",{"_index":1397,"title":{},"content":{"136":{}},"tags":{}}],["397327562",{"_index":481,"title":{},"content":{"41":{}},"tags":{}}],["4",{"_index":834,"title":{"22":{},"90":{},"157":{}},"content":{"23":{},"66":{},"73":{}},"tags":{}}],["4.0.5",{"_index":2217,"title":{},"content":{"79":{}},"tags":{}}],["40",{"_index":1915,"title":{},"content":{"66":{}},"tags":{}}],["42",{"_index":1780,"title":{},"content":{"137":{}},"tags":{}}],["429b",{"_index":1899,"title":{},"content":{"65":{}},"tags":{}}],["43",{"_index":1257,"title":{},"content":{"133":{}},"tags":{}}],["47",{"_index":1269,"title":{},"content":{"133":{}},"tags":{}}],["4bae",{"_index":2511,"title":{},"content":{"87":{}},"tags":{}}],["4ce5",{"_index":2510,"title":{},"content":{"87":{}},"tags":{}}],["5",{"_index":229,"title":{"23":{},"160":{}},"content":{"1":{},"24":{},"73":{}},"tags":{}}],["5.3.0",{"_index":2218,"title":{},"content":{"79":{},"103":{}},"tags":{}}],["50",{"_index":540,"title":{},"content":{"41":{},"136":{},"137":{}},"tags":{}}],["500",{"_index":2241,"title":{},"content":{"79":{},"81":{}},"tags":{}}],["50000",{"_index":1913,"title":{},"content":{"66":{}},"tags":{}}],["56",{"_index":1782,"title":{},"content":{"137":{},"159":{},"160":{}},"tags":{}}],["57",{"_index":1252,"title":{},"content":{"133":{}},"tags":{}}],["5a269aa1",{"_index":1897,"title":{},"content":{"65":{}},"tags":{}}],["6",{"_index":2002,"title":{},"content":{"73":{}},"tags":{}}],["6.10.2",{"_index":2216,"title":{},"content":{"79":{}},"tags":{}}],["7",{"_index":828,"title":{},"content":{"21":{},"73":{}},"tags":{}}],["70",{"_index":1288,"title":{},"content":{"135":{}},"tags":{}}],["77",{"_index":1781,"title":{},"content":{"137":{}},"tags":{}}],["8",{"_index":2014,"title":{},"content":{"73":{}},"tags":{}}],["80",{"_index":1270,"title":{},"content":{"115":{},"133":{}},"tags":{}}],["88",{"_index":1263,"title":{},"content":{"133":{}},"tags":{}}],["9",{"_index":2023,"title":{},"content":{"73":{}},"tags":{}}],["9f4d",{"_index":2512,"title":{},"content":{"87":{}},"tags":{}}],["__dev__",{"_index":190,"title":{},"content":{"1":{},"130":{},"136":{}},"tags":{}}],["__dirnam",{"_index":2560,"title":{},"content":{"96":{}},"tags":{}}],["_layout.tsx",{"_index":1066,"title":{},"content":{"131":{}},"tags":{}}],["_props.navigation.navigate(\"cod",{"_index":2201,"title":{},"content":{"122":{}},"tags":{}}],["aar",{"_index":1970,"title":{"70":{}},"content":{"71":{},"74":{}},"tags":{}}],["abov",{"_index":1646,"title":{},"content":{"76":{},"93":{},"137":{}},"tags":{}}],["absolut",{"_index":1268,"title":{},"content":{"93":{},"133":{}},"tags":{}}],["absolute\",};const",{"_index":2206,"title":{},"content":{"122":{}},"tags":{}}],["accept",{"_index":701,"title":{},"content":{"21":{},"33":{}},"tags":{}}],["access",{"_index":94,"title":{"1":{}},"content":{"1":{},"5":{},"7":{},"8":{},"14":{},"41":{},"66":{},"109":{},"110":{},"112":{},"113":{},"119":{},"130":{},"136":{}},"tags":{"1":{},"3":{},"107":{}}}],["accessibilityact",{"_index":617,"title":{},"content":{"7":{},"136":{}},"tags":{}}],["accessibilityhint",{"_index":1513,"title":{},"content":{"136":{}},"tags":{}}],["accessibilityhintprop",{"_index":1509,"title":{},"content":{"136":{}},"tags":{}}],["accessibilitylabel",{"_index":1511,"title":{},"content":{"66":{},"136":{}},"tags":{}}],["accessibilitylabel={episode.datepublished.accessibilitylabel",{"_index":1543,"title":{},"content":{"136":{}},"tags":{}}],["accessibilitylabel={episode.duration.accessibilitylabel",{"_index":1545,"title":{},"content":{"136":{}},"tags":{}}],["accessibilitylabel={translate(\"demopodcastlistscreen.accessibility.switch",{"_index":1481,"title":{},"content":{"136":{}},"tags":{}}],["accessibilityprop",{"_index":1399,"title":{},"content":{"136":{}},"tags":{}}],["accessibl",{"_index":240,"title":{},"content":{"2":{}},"tags":{}}],["accessori",{"_index":2403,"title":{"153":{}},"content":{"153":{}},"tags":{}}],["accomplish",{"_index":28,"title":{},"content":{"66":{},"143":{}},"tags":{}}],["account",{"_index":267,"title":{},"content":{"17":{},"21":{},"39":{},"41":{},"85":{}},"tags":{}}],["achiev",{"_index":895,"title":{},"content":{"24":{},"119":{},"139":{}},"tags":{}}],["action",{"_index":711,"title":{},"content":{"33":{},"34":{},"65":{},"66":{},"79":{},"80":{},"110":{},"112":{},"121":{},"122":{},"136":{}},"tags":{}}],["actions((self",{"_index":2131,"title":{},"content":{"121":{}},"tags":{}}],["actions((stor",{"_index":721,"title":{},"content":{"33":{},"34":{}},"tags":{}}],["actions(withsetpropact",{"_index":2130,"title":{},"content":{"121":{}},"tags":{}}],["activ",{"_index":2638,"title":{},"content":{"110":{},"112":{}},"tags":{}}],["activeopacity={1",{"_index":2391,"title":{},"content":{"151":{},"156":{},"159":{},"160":{}},"tags":{}}],["activityind",{"_index":1400,"title":{},"content":{"136":{}},"tags":{}}],["actual",{"_index":193,"title":{},"content":{"1":{},"23":{},"119":{}},"tags":{}}],["ad",{"_index":19,"title":{"135":{}},"content":{"19":{},"21":{},"35":{},"40":{},"65":{},"66":{},"76":{},"101":{},"122":{},"125":{},"131":{},"140":{},"142":{},"152":{},"157":{}},"tags":{}}],["adapt",{"_index":2525,"title":{},"content":{"90":{}},"tags":{}}],["adb",{"_index":2050,"title":{},"content":{"55":{},"112":{}},"tags":{}}],["add",{"_index":91,"title":{"6":{},"43":{},"80":{},"152":{},"153":{},"154":{},"155":{},"157":{},"158":{},"159":{},"160":{}},"content":{"7":{},"12":{},"13":{},"19":{},"21":{},"24":{},"34":{},"39":{},"41":{},"44":{},"46":{},"59":{},"65":{},"66":{},"67":{},"79":{},"80":{},"81":{},"87":{},"90":{},"94":{},"95":{},"96":{},"101":{},"105":{},"119":{},"121":{},"126":{},"130":{},"131":{},"134":{},"136":{},"137":{},"147":{},"150":{},"151":{},"153":{},"154":{},"155":{},"158":{},"159":{},"160":{}},"tags":{}}],["add_ssh_key",{"_index":442,"title":{},"content":{"41":{}},"tags":{}}],["addcode(cod",{"_index":2132,"title":{},"content":{"121":{}},"tags":{}}],["addit",{"_index":49,"title":{"140":{}},"content":{"24":{},"25":{},"40":{},"41":{},"78":{},"128":{},"131":{},"144":{},"149":{},"151":{}},"tags":{}}],["addition",{"_index":1835,"title":{},"content":{"140":{},"154":{}},"tags":{}}],["address",{"_index":407,"title":{},"content":{"41":{},"132":{}},"tags":{}}],["adher",{"_index":1641,"title":{},"content":{"137":{}},"tags":{}}],["adjac",{"_index":587,"title":{},"content":{"5":{}},"tags":{}}],["adjust",{"_index":2531,"title":{},"content":{"90":{}},"tags":{}}],["adopt",{"_index":2030,"title":{},"content":{"50":{}},"tags":{}}],["advanc",{"_index":299,"title":{},"content":{"39":{}},"tags":{}}],["advand",{"_index":1902,"title":{},"content":{"66":{}},"tags":{}}],["advic",{"_index":636,"title":{},"content":{"8":{}},"tags":{}}],["again",{"_index":873,"title":{},"content":{"23":{},"96":{},"105":{},"138":{}},"tags":{}}],["against",{"_index":2587,"title":{},"content":{"105":{}},"tags":{}}],["ahead",{"_index":839,"title":{},"content":{"22":{},"66":{}},"tags":{}}],["air",{"_index":776,"title":{},"content":{"16":{},"23":{}},"tags":{}}],["alert",{"_index":891,"title":{},"content":{"24":{},"122":{}},"tags":{}}],["alert.alert(\"cod",{"_index":2185,"title":{},"content":{"122":{}},"tags":{}}],["alia",{"_index":973,"title":{},"content":{"127":{}},"tags":{}}],["alias",{"_index":1204,"title":{},"content":{"133":{}},"tags":{}}],["aligncont",{"_index":1395,"title":{},"content":{"136":{}},"tags":{}}],["alignitem",{"_index":2211,"title":{},"content":{"122":{}},"tags":{}}],["alignself",{"_index":1567,"title":{},"content":{"136":{},"137":{}},"tags":{}}],["allow",{"_index":106,"title":{},"content":{"1":{},"5":{},"39":{},"41":{},"66":{},"79":{},"93":{},"125":{}},"tags":{}}],["allowfontsc",{"_index":168,"title":{},"content":{"1":{}},"tags":{}}],["allowprovisioningupd",{"_index":378,"title":{},"content":{"41":{}},"tags":{}}],["almostther",{"_index":1955,"title":{},"content":{"60":{}},"tags":{}}],["along",{"_index":53,"title":{},"content":{"44":{},"144":{}},"tags":{}}],["aloud",{"_index":2648,"title":{},"content":{"110":{}},"tags":{}}],["alreadi",{"_index":260,"title":{},"content":{"17":{},"38":{},"40":{},"64":{},"72":{},"85":{},"119":{},"127":{},"150":{}},"tags":{}}],["alway",{"_index":89,"title":{},"content":{"66":{},"112":{},"147":{}},"tags":{}}],["and/or",{"_index":1069,"title":{},"content":{"131":{}},"tags":{}}],["android",{"_index":103,"title":{"70":{},"111":{}},"content":{"1":{},"19":{},"20":{},"21":{},"53":{},"55":{},"65":{},"71":{},"73":{},"74":{},"81":{},"85":{},"89":{},"90":{},"101":{},"103":{},"113":{},"119":{},"136":{}},"tags":{"3":{},"70":{},"107":{}}}],["android/gradlew",{"_index":2027,"title":{},"content":{"73":{}},"tags":{}}],["android_ndk_vers",{"_index":1995,"title":{},"content":{"73":{}},"tags":{}}],["androiddrag",{"_index":2529,"title":{},"content":{"90":{}},"tags":{}}],["androidsdk",{"_index":2505,"title":{},"content":{"85":{}},"tags":{}}],["anim",{"_index":1405,"title":{},"content":{"71":{},"105":{},"136":{},"137":{}},"tags":{}}],["animated.view",{"_index":1527,"title":{},"content":{"136":{}},"tags":{}}],["animatedlikebuttonstyl",{"_index":1499,"title":{},"content":{"136":{}},"tags":{}}],["animatedunlikebuttonstyl",{"_index":1505,"title":{},"content":{"136":{}},"tags":{}}],["announc",{"_index":599,"title":{},"content":{"6":{}},"tags":{}}],["anoth",{"_index":586,"title":{},"content":{"5":{},"8":{},"34":{},"65":{},"66":{},"71":{},"131":{},"135":{}},"tags":{}}],["answer",{"_index":791,"title":{},"content":{"19":{}},"tags":{}}],["any),\\n",{"_index":1032,"title":{},"content":{"128":{}},"tags":{}}],["anymor",{"_index":1686,"title":{},"content":{"137":{}},"tags":{}}],["anyon",{"_index":43,"title":{},"content":{"144":{}},"tags":{}}],["anywher",{"_index":2650,"title":{},"content":{"110":{}},"tags":{}}],["api",{"_index":681,"title":{"33":{},"34":{}},"content":{"32":{},"33":{},"34":{},"35":{},"36":{},"60":{}},"tags":{}}],["api.apisauce.setheader(\"author",{"_index":742,"title":{},"content":{"34":{}},"tags":{}}],["apiconfig",{"_index":689,"title":{},"content":{"33":{}},"tags":{}}],["apisauc",{"_index":676,"title":{"32":{}},"content":{"32":{},"33":{},"34":{},"35":{}},"tags":{"32":{}}}],["apisauceinst",{"_index":694,"title":{},"content":{"33":{}},"tags":{}}],["apk",{"_index":808,"title":{},"content":{"20":{},"89":{},"90":{}},"tags":{}}],["app",{"_index":48,"title":{},"content":{"1":{},"5":{},"13":{},"20":{},"23":{},"24":{},"28":{},"30":{},"38":{},"41":{},"55":{},"60":{},"65":{},"71":{},"79":{},"80":{},"81":{},"89":{},"90":{},"95":{},"96":{},"97":{},"101":{},"102":{},"118":{},"119":{},"125":{},"127":{},"128":{},"130":{},"131":{},"134":{},"137":{},"144":{}},"tags":{}}],["app'",{"_index":950,"title":{},"content":{"125":{}},"tags":{}}],["app(prop",{"_index":2333,"title":{},"content":{"81":{}},"tags":{}}],["app.config.j",{"_index":904,"title":{},"content":{"25":{}},"tags":{}}],["app.config.t",{"_index":977,"title":{},"content":{"127":{}},"tags":{}}],["app.j",{"_index":2033,"title":{},"content":{"53":{},"55":{}},"tags":{}}],["app.json",{"_index":797,"title":{},"content":{"19":{},"24":{},"25":{},"65":{},"87":{},"102":{},"119":{},"126":{}},"tags":{}}],["app.tsx",{"_index":967,"title":{},"content":{"79":{},"80":{},"81":{},"127":{},"128":{},"130":{}},"tags":{}}],["app/**/*.{js,jsx,json,md,ts,tsx",{"_index":2045,"title":{},"content":{"55":{}},"tags":{}}],["app/**/*.{js,jsx,json,md,ts,tsx}\\\"\",\"lint",{"_index":983,"title":{},"content":{"128":{}},"tags":{}}],["app/_layout.tsx",{"_index":1038,"title":{},"content":{"130":{}},"tags":{}}],["app/app.tsx",{"_index":2453,"title":{},"content":{"158":{}},"tags":{}}],["app/compon",{"_index":2101,"title":{},"content":{"80":{},"120":{},"121":{}},"tags":{}}],["app/components\";import",{"_index":2167,"title":{},"content":{"122":{}},"tags":{}}],["app/components/index.t",{"_index":1006,"title":{},"content":{"128":{}},"tags":{}}],["app/components/profile.tsx",{"_index":1849,"title":{},"content":{"45":{},"46":{}},"tags":{}}],["app/components/selectfield.tsx",{"_index":2376,"title":{},"content":{"151":{}},"tags":{}}],["app/components/spec",{"_index":1852,"title":{},"content":{"46":{}},"tags":{}}],["app/components/specs/profile.spec.tsx",{"_index":1858,"title":{},"content":{"46":{}},"tags":{}}],["app/components/text\"import",{"_index":1020,"title":{},"content":{"128":{}},"tags":{}}],["app/i18n\";import",{"_index":997,"title":{},"content":{"128":{}},"tags":{}}],["app/i18n/en\";import",{"_index":1001,"title":{},"content":{"128":{}},"tags":{}}],["app/model",{"_index":2144,"title":{},"content":{"121":{}},"tags":{}}],["app/models\";import",{"_index":2169,"title":{},"content":{"122":{}},"tags":{}}],["app/models/authenticationstore.t",{"_index":710,"title":{},"content":{"33":{}},"tags":{}}],["app/models/index.t",{"_index":1033,"title":{},"content":{"128":{}},"tags":{}}],["app/models/rootstore.t",{"_index":1024,"title":{},"content":{"128":{}},"tags":{}}],["app/navig",{"_index":2141,"title":{},"content":{"121":{}},"tags":{}}],["app/navigators/demonavigator.tsx",{"_index":1277,"title":{},"content":{"135":{}},"tags":{}}],["app/navigators/navigationutilities\";import",{"_index":992,"title":{},"content":{"128":{}},"tags":{}}],["app/screens/demoshowroomscreen.tsx",{"_index":2565,"title":{},"content":{"97":{}},"tags":{}}],["app/screens/loginscreen.tsx",{"_index":753,"title":{},"content":{"22":{},"34":{}},"tags":{}}],["app/services/api",{"_index":737,"title":{},"content":{"34":{}},"tags":{}}],["app/services/api/api.t",{"_index":684,"title":{},"content":{"33":{}},"tags":{}}],["app/store.t",{"_index":2247,"title":{},"content":{"80":{}},"tags":{}}],["app/store/counterslic",{"_index":2300,"title":{},"content":{"80":{}},"tags":{}}],["app/store/stor",{"_index":2299,"title":{},"content":{"80":{}},"tags":{}}],["app/them",{"_index":2145,"title":{},"content":{"121":{},"122":{}},"tags":{}}],["app/theme\"import",{"_index":1019,"title":{},"content":{"128":{}},"tags":{}}],["app/utils/storage\";import",{"_index":989,"title":{},"content":{"128":{}},"tags":{}}],["app/utils/storage.tsx",{"_index":1937,"title":{},"content":{"60":{}},"tags":{}}],["appar",{"_index":468,"title":{},"content":{"41":{}},"tags":{}}],["appbuildvers",{"_index":1601,"title":{},"content":{"136":{}},"tags":{}}],["appdispatch",{"_index":2263,"title":{},"content":{"80":{},"81":{}},"tags":{}}],["appear",{"_index":2340,"title":{},"content":{"81":{},"112":{}},"tags":{}}],["appearsonindex={0",{"_index":2472,"title":{},"content":{"159":{},"160":{}},"tags":{}}],["append",{"_index":1008,"title":{},"content":{"128":{}},"tags":{}}],["appet",{"_index":782,"title":{"17":{},"85":{}},"content":{},"tags":{}}],["appid",{"_index":1595,"title":{},"content":{"65":{},"66":{},"136":{}},"tags":{}}],["appl",{"_index":408,"title":{},"content":{"41":{}},"tags":{}}],["appli",{"_index":619,"title":{},"content":{"7":{},"23":{},"72":{},"78":{},"118":{},"136":{},"137":{}},"tags":{}}],["applic",{"_index":848,"title":{},"content":{"22":{},"58":{},"63":{},"71":{},"103":{},"119":{},"125":{},"127":{},"132":{},"136":{},"140":{}},"tags":{}}],["application'",{"_index":2024,"title":{},"content":{"73":{}},"tags":{}}],["application.applicationid",{"_index":1596,"title":{},"content":{"136":{}},"tags":{}}],["application.applicationnam",{"_index":1598,"title":{},"content":{"136":{}},"tags":{}}],["application.nativeapplicationvers",{"_index":1600,"title":{},"content":{"136":{}},"tags":{}}],["application.nativebuildvers",{"_index":1602,"title":{},"content":{"136":{}},"tags":{}}],["application/json",{"_index":702,"title":{},"content":{"33":{}},"tags":{}}],["appnam",{"_index":1597,"title":{},"content":{"136":{}},"tags":{}}],["appnavig",{"_index":2289,"title":{},"content":{"80":{},"81":{},"158":{}},"tags":{}}],["appprop",{"_index":2334,"title":{},"content":{"81":{}},"tags":{}}],["appreci",{"_index":76,"title":{},"content":{"145":{}},"tags":{}}],["approach",{"_index":889,"title":{},"content":{"24":{},"71":{},"80":{}},"tags":{}}],["appropri",{"_index":1789,"title":{},"content":{"90":{},"137":{}},"tags":{}}],["approxim",{"_index":2590,"title":{},"content":{"105":{}},"tags":{}}],["appstackscreenprop",{"_index":2099,"title":{},"content":{"80":{},"120":{},"121":{},"122":{}},"tags":{}}],["appstackscreenprops<\"cod",{"_index":2147,"title":{},"content":{"121":{}},"tags":{}}],["appstackscreenprops<\"welcom",{"_index":2103,"title":{},"content":{"80":{},"120":{},"122":{}},"tags":{}}],["appstat",{"_index":121,"title":{},"content":{"1":{}},"tags":{}}],["appstate.addeventlistener(\"chang",{"_index":202,"title":{},"content":{"1":{}},"tags":{}}],["appstate.currentst",{"_index":199,"title":{},"content":{"1":{}},"tags":{}}],["appstatevis",{"_index":196,"title":{},"content":{"1":{}},"tags":{}}],["appstor",{"_index":371,"title":{},"content":{"41":{}},"tags":{}}],["appvers",{"_index":1599,"title":{},"content":{"136":{}},"tags":{}}],["arch",{"_index":515,"title":{},"content":{"41":{},"73":{}},"tags":{}}],["architectur",{"_index":2001,"title":{},"content":{"73":{}},"tags":{}}],["archiv",{"_index":1996,"title":{},"content":{"73":{}},"tags":{}}],["area",{"_index":1283,"title":{},"content":{"110":{},"122":{},"135":{},"159":{},"160":{}},"tags":{}}],["arefontsload",{"_index":2243,"title":{},"content":{"79":{}},"tags":{}}],["aren't",{"_index":612,"title":{},"content":{"7":{},"134":{}},"tags":{}}],["arg",{"_index":1806,"title":{},"content":{"138":{}},"tags":{}}],["argtype.str",{"_index":1805,"title":{},"content":{"138":{}},"tags":{}}],["argument",{"_index":1848,"title":{},"content":{"45":{},"80":{},"115":{}},"tags":{}}],["aris",{"_index":1972,"title":{},"content":{"71":{}},"tags":{}}],["arm",{"_index":2000,"title":{},"content":{"73":{}},"tags":{}}],["around",{"_index":445,"title":{},"content":{"41":{},"105":{},"112":{},"133":{}},"tags":{}}],["array",{"_index":2123,"title":{},"content":{"96":{},"121":{},"154":{}},"tags":{}}],["array.filter((v",{"_index":2486,"title":{},"content":{"160":{}},"tags":{}}],["arriv",{"_index":1197,"title":{},"content":{"133":{}},"tags":{}}],["articl",{"_index":671,"title":{},"content":{"30":{},"112":{}},"tags":{}}],["aschild",{"_index":1689,"title":{},"content":{"137":{}},"tags":{}}],["asid",{"_index":1327,"title":{},"content":{"136":{}},"tags":{}}],["ask",{"_index":1200,"title":{},"content":{"133":{}},"tags":{}}],["aspect",{"_index":1821,"title":{},"content":{"139":{}},"tags":{}}],["assert",{"_index":1887,"title":{},"content":{"65":{}},"tags":{}}],["assertvis",{"_index":1885,"title":{},"content":{"65":{},"66":{}},"tags":{}}],["asset",{"_index":1074,"title":{},"content":{"131":{}},"tags":{}}],["assist",{"_index":2684,"title":{"113":{}},"content":{"113":{}},"tags":{}}],["associ",{"_index":1922,"title":{},"content":{"66":{}},"tags":{}}],["assum",{"_index":2558,"title":{},"content":{"95":{}},"tags":{}}],["async",{"_index":703,"title":{},"content":{"33":{},"60":{},"81":{},"103":{},"136":{}},"tags":{}}],["asyncstorag",{"_index":1931,"title":{},"content":{"58":{},"60":{},"81":{}},"tags":{"57":{}}}],["asyncstorage.clear",{"_index":1966,"title":{},"content":{"60":{}},"tags":{}}],["asyncstorage.getitem(key",{"_index":1943,"title":{},"content":{"60":{}},"tags":{}}],["asyncstorage.removeitem(key",{"_index":1962,"title":{},"content":{"60":{}},"tags":{}}],["asyncstorage.setitem(key",{"_index":1949,"title":{},"content":{"60":{}},"tags":{}}],["atl",{"_index":2429,"title":{},"content":{"156":{},"160":{}},"tags":{}}],["attempt",{"_index":2417,"title":{},"content":{"102":{},"155":{}},"tags":{}}],["attemptscount",{"_index":1117,"title":{},"content":{"132":{}},"tags":{}}],["audit",{"_index":2618,"title":{"115":{}},"content":{"115":{},"116":{}},"tags":{}}],["auth",{"_index":414,"title":{"32":{},"33":{},"34":{}},"content":{"33":{},"34":{},"36":{},"41":{},"125":{},"130":{}},"tags":{}}],["authemail",{"_index":719,"title":{},"content":{"33":{},"34":{},"132":{}},"tags":{}}],["authent",{"_index":679,"title":{},"content":{"32":{},"33":{},"34":{},"65":{},"130":{},"131":{},"132":{},"133":{},"134":{},"139":{}},"tags":{"32":{}}}],["authenticationstor",{"_index":725,"title":{},"content":{"33":{},"34":{},"131":{},"132":{},"133":{},"136":{}},"tags":{}}],["authenticationstoremodel",{"_index":715,"title":{},"content":{"33":{}},"tags":{}}],["authenticationstoresnapshot",{"_index":727,"title":{},"content":{"33":{}},"tags":{}}],["author",{"_index":1828,"title":{},"content":{"140":{}},"tags":{}}],["authpassword",{"_index":1110,"title":{},"content":{"132":{}},"tags":{}}],["authpasswordinput",{"_index":1108,"title":{},"content":{"132":{}},"tags":{}}],["authpasswordinput.current?.focu",{"_index":1163,"title":{},"content":{"132":{}},"tags":{}}],["authstor",{"_index":735,"title":{},"content":{"34":{}},"tags":{}}],["authtoken",{"_index":717,"title":{},"content":{"33":{},"34":{}},"tags":{}}],["auto",{"_index":2058,"title":{},"content":{"55":{}},"tags":{}}],["autocapitalize=\"non",{"_index":1153,"title":{},"content":{"132":{}},"tags":{}}],["autocomplete=\"email",{"_index":1154,"title":{},"content":{"132":{}},"tags":{}}],["autocomplete=\"password",{"_index":1167,"title":{},"content":{"132":{}},"tags":{}}],["autocorrect={fals",{"_index":1155,"title":{},"content":{"132":{}},"tags":{}}],["automat",{"_index":247,"title":{},"content":{"37":{},"43":{},"125":{}},"tags":{}}],["avail",{"_index":1919,"title":{},"content":{"66":{},"71":{},"110":{},"115":{}},"tags":{}}],["averageitemlength",{"_index":1738,"title":{},"content":{"105":{},"137":{}},"tags":{}}],["await",{"_index":1438,"title":{},"content":{"60":{},"120":{},"122":{},"136":{}},"tags":{}}],["awar",{"_index":653,"title":{},"content":{"30":{}},"tags":{}}],["away",{"_index":865,"title":{},"content":{"23":{},"60":{}},"tags":{}}],["babel",{"_index":911,"title":{"96":{}},"content":{"12":{},"13":{},"94":{},"96":{}},"tags":{"92":{}}}],["babel.config.j",{"_index":914,"title":{},"content":{"13":{},"96":{}},"tags":{}}],["babel/plugin",{"_index":916,"title":{},"content":{"13":{}},"tags":{}}],["babelrc",{"_index":915,"title":{},"content":{"13":{}},"tags":{}}],["back",{"_index":24,"title":{"146":{}},"content":{"1":{},"66":{},"79":{},"121":{},"122":{},"133":{},"138":{},"142":{}},"tags":{}}],["backdropcomponent={(prop",{"_index":2471,"title":{},"content":{"159":{},"160":{}},"tags":{}}],["background",{"_index":1436,"title":{},"content":{"136":{}},"tags":{}}],["backgroundcolor",{"_index":223,"title":{},"content":{"1":{},"80":{},"122":{},"133":{},"135":{},"136":{},"137":{}},"tags":{}}],["backward",{"_index":2627,"title":{},"content":{"115":{}},"tags":{}}],["bacon",{"_index":1827,"title":{},"content":{"140":{}},"tags":{}}],["barcod",{"_index":2079,"title":{},"content":{"118":{},"122":{}},"tags":{}}],["bare",{"_index":926,"title":{},"content":{"13":{},"49":{},"118":{}},"tags":{}}],["base",{"_index":45,"title":{"129":{}},"content":{"1":{},"7":{},"125":{},"127":{},"131":{},"144":{}},"tags":{}}],["baseurl",{"_index":698,"title":{"92":{}},"content":{"33":{},"93":{},"95":{},"98":{},"99":{}},"tags":{}}],["bash",{"_index":508,"title":{},"content":{"41":{},"64":{}},"tags":{}}],["basic",{"_index":280,"title":{},"content":{"39":{},"105":{},"110":{},"112":{},"159":{}},"tags":{}}],["be",{"_index":357,"title":{},"content":{"41":{},"80":{},"97":{}},"tags":{}}],["bearer",{"_index":743,"title":{},"content":{"34":{}},"tags":{}}],["befor",{"_index":352,"title":{},"content":{"6":{},"41":{},"66":{},"79":{},"120":{},"121":{},"137":{}},"tags":{}}],["before_al",{"_index":359,"title":{},"content":{"41":{}},"tags":{}}],["begin",{"_index":2161,"title":{},"content":{"110":{},"122":{}},"tags":{}}],["beginn",{"_index":2647,"title":{},"content":{"110":{}},"tags":{}}],["behav",{"_index":905,"title":{},"content":{"25":{}},"tags":{}}],["behavior",{"_index":887,"title":{},"content":{"24":{}},"tags":{}}],["behind",{"_index":1975,"title":{},"content":{"71":{}},"tags":{}}],["belong",{"_index":15,"title":{},"content":{"142":{}},"tags":{}}],["below",{"_index":309,"title":{},"content":{"25":{},"40":{},"41":{},"72":{},"79":{},"137":{}},"tags":{}}],["beta",{"_index":251,"title":{},"content":{"37":{},"41":{}},"tags":{}}],["better",{"_index":890,"title":{},"content":{"24":{},"81":{}},"tags":{}}],["between",{"_index":628,"title":{"100":{}},"content":{"8":{},"104":{},"121":{},"133":{}},"tags":{}}],["bf30",{"_index":1900,"title":{},"content":{"65":{}},"tags":{}}],["big",{"_index":175,"title":{},"content":{"1":{},"73":{}},"tags":{}}],["bigger",{"_index":136,"title":{},"content":{"1":{}},"tags":{}}],["bin/bash",{"_index":486,"title":{},"content":{"41":{}},"tags":{}}],["bin/downloadexpoapp.sh",{"_index":2063,"title":{},"content":{"55":{}},"tags":{}}],["bin/exponent.app",{"_index":2068,"title":{},"content":{"55":{}},"tags":{}}],["bin/postinstal",{"_index":2057,"title":{},"content":{"55":{}},"tags":{}}],["binari",{"_index":1978,"title":{},"content":{"71":{}},"tags":{}}],["binarypath",{"_index":2067,"title":{},"content":{"55":{}},"tags":{}}],["bind",{"_index":921,"title":{},"content":{"13":{},"80":{}},"tags":{}}],["bit",{"_index":1635,"title":{},"content":{"66":{},"81":{},"119":{},"136":{}},"tags":{}}],["blazer",{"_index":2401,"title":{},"content":{"151":{},"156":{},"160":{}},"tags":{}}],["blog",{"_index":354,"title":{},"content":{"7":{},"41":{}},"tags":{}}],["bo",{"_index":2431,"title":{},"content":{"156":{},"160":{}},"tags":{}}],["boilerpl",{"_index":16,"title":{},"content":{"32":{},"33":{},"79":{},"119":{},"132":{},"133":{},"138":{},"142":{},"144":{},"150":{}},"tags":{}}],["boolean",{"_index":1490,"title":{},"content":{"60":{},"136":{},"154":{},"156":{},"159":{},"160":{}},"tags":{}}],["boot",{"_index":2095,"title":{},"content":{"90":{},"119":{}},"tags":{}}],["bootsplash",{"_index":2035,"title":{},"content":{"54":{}},"tags":{}}],["bootstrap",{"_index":951,"title":{},"content":{"126":{}},"tags":{}}],["bordercolor",{"_index":230,"title":{},"content":{"1":{},"136":{}},"tags":{}}],["borderradiu",{"_index":228,"title":{},"content":{"1":{},"122":{},"136":{}},"tags":{}}],["bordertopcolor",{"_index":1316,"title":{},"content":{"135":{}},"tags":{}}],["bordertopleftradiu",{"_index":1259,"title":{},"content":{"133":{}},"tags":{}}],["bordertoprightradiu",{"_index":1261,"title":{},"content":{"133":{}},"tags":{}}],["borderwidth",{"_index":232,"title":{},"content":{"1":{}},"tags":{}}],["both",{"_index":746,"title":{},"content":{"19":{},"34":{},"35":{},"46":{},"49":{},"112":{},"118":{},"119":{},"122":{},"137":{},"139":{}},"tags":{}}],["bottom",{"_index":1142,"title":{"149":{}},"content":{"80":{},"121":{},"132":{},"133":{},"135":{},"136":{},"149":{},"150":{},"159":{},"160":{},"161":{}},"tags":{}}],["bottomcontain",{"_index":1255,"title":{},"content":{"133":{}},"tags":{}}],["bottomcontainerinset",{"_index":1227,"title":{},"content":{"133":{}},"tags":{}}],["bottominset={bottom",{"_index":2475,"title":{},"content":{"159":{},"160":{}},"tags":{}}],["bottomsepar",{"_index":1366,"title":{},"content":{"136":{}},"tags":{}}],["bottomsheet",{"_index":2452,"title":{},"content":{"158":{}},"tags":{}}],["bottomsheetbackdrop",{"_index":2454,"title":{},"content":{"159":{},"160":{}},"tags":{}}],["bottomsheetflatlist",{"_index":2455,"title":{},"content":{"159":{},"160":{}},"tags":{}}],["bottomsheetfoot",{"_index":2456,"title":{},"content":{"159":{},"160":{}},"tags":{}}],["bottomsheetmod",{"_index":2449,"title":{},"content":{"157":{},"158":{},"159":{},"160":{}},"tags":{}}],["bottomsheetmodalprovid",{"_index":2451,"title":{"158":{}},"content":{"158":{}},"tags":{}}],["bottomtabnavigationopt",{"_index":128,"title":{},"content":{"1":{}},"tags":{}}],["boundari",{"_index":1056,"title":{},"content":{"130":{}},"tags":{}}],["box",{"_index":465,"title":{},"content":{"41":{},"139":{}},"tags":{}}],["branch",{"_index":496,"title":{},"content":{"23":{},"41":{},"71":{},"76":{},"115":{}},"tags":{}}],["break",{"_index":146,"title":{},"content":{"1":{}},"tags":{}}],["breez",{"_index":682,"title":{},"content":{"32":{}},"tags":{}}],["brew",{"_index":1873,"title":{},"content":{"64":{}},"tags":{}}],["bring",{"_index":937,"title":{},"content":{"125":{},"136":{}},"tags":{}}],["bug",{"_index":879,"title":{},"content":{"23":{},"71":{}},"tags":{}}],["build",{"_index":37,"title":{"20":{},"21":{},"88":{},"89":{}},"content":{"20":{},"21":{},"23":{},"24":{},"26":{},"32":{},"37":{},"39":{},"41":{},"55":{},"65":{},"71":{},"72":{},"73":{},"79":{},"81":{},"84":{},"85":{},"87":{},"88":{},"89":{},"90":{},"101":{},"119":{},"134":{},"136":{},"143":{},"144":{}},"tags":{}}],["build/build",{"_index":2524,"title":{},"content":{"90":{}},"tags":{}}],["build:configur",{"_index":790,"title":{},"content":{"19":{},"87":{}},"tags":{}}],["build:detox",{"_index":2059,"title":{},"content":{"55":{}},"tags":{}}],["build_ios_app",{"_index":372,"title":{},"content":{"41":{}},"tags":{}}],["buildtyp",{"_index":807,"title":{},"content":{"20":{}},"tags":{}}],["built",{"_index":1832,"title":{},"content":{"81":{},"140":{}},"tags":{}}],["bump",{"_index":363,"title":{},"content":{"41":{}},"tags":{}}],["bunch",{"_index":2620,"title":{},"content":{"115":{}},"tags":{}}],["bundl",{"_index":513,"title":{},"content":{"20":{},"41":{},"130":{}},"tags":{}}],["bundleidentifi",{"_index":1881,"title":{},"content":{"65":{}},"tags":{}}],["bundler",{"_index":2570,"title":{},"content":{"97":{}},"tags":{}}],["burn",{"_index":1964,"title":{},"content":{"60":{}},"tags":{}}],["button",{"_index":531,"title":{},"content":{"8":{},"41":{},"80":{},"110":{},"120":{},"121":{},"122":{},"132":{},"133":{},"136":{},"159":{},"160":{}},"tags":{}}],["button\";import",{"_index":2459,"title":{},"content":{"159":{}},"tags":{}}],["button={episodestore.favoritesonli",{"_index":1463,"title":{},"content":{"136":{}},"tags":{}}],["buttonaccessoryprop",{"_index":1412,"title":{},"content":{"136":{}},"tags":{}}],["buttoncontain",{"_index":1631,"title":{},"content":{"136":{}},"tags":{}}],["buttonleftaccessori",{"_index":1525,"title":{},"content":{"136":{}},"tags":{}}],["buttononpress={manualrefresh",{"_index":1464,"title":{},"content":{"136":{}},"tags":{}}],["bypass",{"_index":1811,"title":{},"content":{"138":{}},"tags":{}}],["c",{"_index":2060,"title":{},"content":{"55":{},"90":{}},"tags":{}}],["cach",{"_index":330,"title":{},"content":{"14":{},"40":{},"41":{},"76":{},"97":{}},"tags":{}}],["calcul",{"_index":2589,"title":{},"content":{"105":{}},"tags":{}}],["call",{"_index":446,"title":{},"content":{"33":{},"34":{},"41":{},"65":{},"66":{},"79":{},"81":{},"105":{},"131":{},"154":{}},"tags":{}}],["callback",{"_index":2331,"title":{"160":{}},"content":{"81":{},"149":{},"154":{},"160":{}},"tags":{}}],["camera",{"_index":2075,"title":{"122":{}},"content":{"118":{},"119":{},"120":{},"121":{},"122":{},"123":{}},"tags":{}}],["camera\";import",{"_index":2164,"title":{},"content":{"122":{}},"tags":{}}],["camera.getcamerapermissionstatus().then(setcamerapermiss",{"_index":2109,"title":{},"content":{"120":{},"122":{}},"tags":{}}],["camera.requestcamerapermiss",{"_index":2112,"title":{},"content":{"120":{},"122":{}},"tags":{}}],["camerabutton",{"_index":2194,"title":{},"content":{"122":{}},"tags":{}}],["cameracontain",{"_index":2204,"title":{},"content":{"122":{}},"tags":{}}],["camerapermiss",{"_index":2106,"title":{},"content":{"120":{},"122":{}},"tags":{}}],["camerapermissionstatu",{"_index":2100,"title":{},"content":{"120":{},"122":{}},"tags":{}}],["camerapermissiontext",{"_index":2090,"title":{},"content":{"119":{}},"tags":{}}],["can't",{"_index":1976,"title":{},"content":{"71":{},"102":{},"105":{}},"tags":{}}],["canopen",{"_index":1584,"title":{},"content":{"136":{}},"tags":{}}],["card",{"_index":1413,"title":{},"content":{"66":{},"136":{}},"tags":{}}],["care",{"_index":1936,"title":{},"content":{"59":{}},"tags":{}}],["caret",{"_index":2402,"title":{"153":{}},"content":{},"tags":{}}],["caretleft",{"_index":1354,"title":{},"content":{"136":{},"137":{}},"tags":{}}],["caretright",{"_index":1355,"title":{},"content":{"136":{},"137":{}},"tags":{}}],["case",{"_index":1199,"title":{},"content":{"65":{},"66":{},"71":{},"72":{},"90":{},"105":{},"119":{},"133":{}},"tags":{}}],["catch",{"_index":920,"title":{},"content":{"13":{},"60":{},"137":{}},"tags":{}}],["catcherrors={config.catcherror",{"_index":2348,"title":{},"content":{"81":{},"158":{}},"tags":{}}],["caus",{"_index":593,"title":{},"content":{"6":{},"7":{}},"tags":{}}],["caveat",{"_index":1998,"title":{},"content":{"73":{}},"tags":{}}],["cd",{"_index":242,"title":{"37":{}},"content":{"40":{},"42":{},"52":{},"58":{},"65":{},"119":{},"126":{}},"tags":{}}],["celtic",{"_index":2430,"title":{},"content":{"156":{},"160":{}},"tags":{}}],["center",{"_index":1254,"title":{},"content":{"122":{},"133":{},"136":{},"137":{}},"tags":{}}],["cert",{"_index":438,"title":{},"content":{"41":{}},"tags":{}}],["certain",{"_index":110,"title":{},"content":{"1":{}},"tags":{}}],["certif",{"_index":433,"title":{},"content":{"41":{}},"tags":{}}],["cf",{"_index":509,"title":{},"content":{"41":{}},"tags":{}}],["chainreactlogo",{"_index":1332,"title":{},"content":{"136":{}},"tags":{}}],["chang",{"_index":285,"title":{"53":{},"54":{},"60":{},"95":{},"96":{}},"content":{"14":{},"19":{},"22":{},"23":{},"24":{},"25":{},"39":{},"41":{},"55":{},"60":{},"73":{},"81":{},"93":{},"101":{},"109":{},"119":{},"126":{},"136":{},"137":{},"160":{}},"tags":{}}],["channel",{"_index":815,"title":{},"content":{"20":{},"23":{}},"tags":{}}],["channel:cr",{"_index":854,"title":{},"content":{"23":{}},"tags":{}}],["channel:view",{"_index":857,"title":{},"content":{"23":{}},"tags":{}}],["chatti",{"_index":2226,"title":{},"content":{"79":{}},"tags":{}}],["cheatsheet",{"_index":2659,"title":{},"content":{"110":{},"113":{}},"tags":{}}],["check",{"_index":23,"title":{},"content":{"23":{},"24":{},"30":{},"41":{},"64":{},"65":{},"67":{},"73":{},"76":{},"79":{},"101":{},"115":{},"122":{},"131":{},"140":{},"142":{},"150":{},"160":{}},"tags":{}}],["checkautomat",{"_index":896,"title":{},"content":{"24":{}},"tags":{}}],["checkforupdateasync",{"_index":899,"title":{},"content":{"24":{}},"tags":{}}],["checkout",{"_index":322,"title":{},"content":{"40":{},"41":{},"73":{},"76":{}},"tags":{}}],["checkpoint",{"_index":1274,"title":{"134":{}},"content":{},"tags":{}}],["checksum",{"_index":326,"title":{},"content":{"40":{},"41":{},"76":{}},"tags":{}}],["chi",{"_index":2438,"title":{},"content":{"156":{}},"tags":{}}],["child_process",{"_index":1003,"title":{},"content":{"128":{}},"tags":{}}],["children",{"_index":1059,"title":{},"content":{"66":{},"130":{}},"tags":{}}],["choos",{"_index":268,"title":{},"content":{"24":{},"39":{},"40":{},"67":{},"68":{},"76":{}},"tags":{}}],["ci",{"_index":289,"title":{},"content":{"39":{},"40":{},"41":{}},"tags":{}}],["ci/cd",{"_index":257,"title":{},"content":{},"tags":{"37":{},"75":{}}}],["ci:publish",{"_index":2363,"title":{},"content":{"76":{}},"tags":{}}],["ci:setup",{"_index":447,"title":{},"content":{"41":{}},"tags":{}}],["ci:test",{"_index":343,"title":{},"content":{"40":{},"76":{}},"tags":{}}],["ci@your.domain",{"_index":493,"title":{},"content":{"41":{}},"tags":{}}],["circl",{"_index":428,"title":{},"content":{"41":{},"110":{}},"tags":{}}],["circle_branch",{"_index":498,"title":{},"content":{"41":{}},"tags":{}}],["circleci",{"_index":241,"title":{"37":{},"39":{},"75":{}},"content":{"37":{},"39":{},"40":{},"41":{},"42":{},"76":{},"77":{}},"tags":{}}],["circleci/config.yml",{"_index":282,"title":{},"content":{"39":{}},"tags":{}}],["circleci/node:10.11",{"_index":318,"title":{},"content":{"40":{},"76":{}},"tags":{}}],["class",{"_index":685,"title":{},"content":{"33":{}},"tags":{}}],["cle",{"_index":2439,"title":{},"content":{"156":{}},"tags":{}}],["clean",{"_index":1792,"title":{},"content":{"55":{},"65":{},"73":{},"138":{}},"tags":{}}],["cleanup",{"_index":522,"title":{"138":{}},"content":{"41":{},"132":{}},"tags":{}}],["clear",{"_index":597,"title":{},"content":{"6":{},"14":{},"60":{},"65":{},"79":{},"97":{},"105":{},"128":{}},"tags":{}}],["clearer",{"_index":575,"title":{},"content":{"5":{}},"tags":{}}],["clearstat",{"_index":1882,"title":{},"content":{"65":{}},"tags":{}}],["cleartimeout(timeout.curr",{"_index":1742,"title":{},"content":{"105":{},"137":{}},"tags":{}}],["cli",{"_index":784,"title":{"43":{}},"content":{"17":{},"20":{},"45":{},"46":{},"52":{},"58":{},"64":{},"76":{},"78":{},"79":{},"85":{},"88":{},"90":{},"121":{}},"tags":{}}],["cli@latest",{"_index":2085,"title":{},"content":{"119":{}},"tags":{}}],["cli@next",{"_index":952,"title":{},"content":{"121":{},"126":{}},"tags":{}}],["click",{"_index":400,"title":{},"content":{"41":{},"110":{}},"tags":{}}],["client",{"_index":2506,"title":{"90":{}},"content":{"87":{},"90":{}},"tags":{}}],["clone",{"_index":437,"title":{},"content":{"41":{},"73":{}},"tags":{}}],["close",{"_index":866,"title":{},"content":{"23":{},"60":{}},"tags":{}}],["closecamera",{"_index":2207,"title":{},"content":{"122":{}},"tags":{}}],["cloud",{"_index":1927,"title":{},"content":{"67":{}},"tags":{}}],["cng",{"_index":1892,"title":{"100":{},"101":{},"102":{}},"content":{"65":{},"100":{},"101":{},"102":{},"104":{}},"tags":{}}],["cocoapod",{"_index":501,"title":{},"content":{"41":{},"85":{}},"tags":{}}],["code",{"_index":284,"title":{"60":{},"121":{},"138":{},"156":{}},"content":{"22":{},"25":{},"39":{},"58":{},"71":{},"73":{},"79":{},"84":{},"101":{},"102":{},"119":{},"121":{},"122":{},"137":{},"138":{},"139":{},"151":{},"152":{},"155":{}},"tags":{}}],["code.valu",{"_index":2182,"title":{},"content":{"122":{}},"tags":{}}],["codes.every((cod",{"_index":2181,"title":{},"content":{"122":{}},"tags":{}}],["codescann",{"_index":2174,"title":{},"content":{"122":{}},"tags":{}}],["codescanner={codescann",{"_index":2190,"title":{},"content":{"122":{}},"tags":{}}],["codesign",{"_index":423,"title":{},"content":{"41":{}},"tags":{}}],["codesscreen",{"_index":2148,"title":{},"content":{"121":{}},"tags":{}}],["codesscreenprop",{"_index":2146,"title":{},"content":{"121":{}},"tags":{}}],["codestor",{"_index":2120,"title":{},"content":{"121":{},"122":{}},"tags":{}}],["codestore.addcode(code.valu",{"_index":2183,"title":{},"content":{"122":{}},"tags":{}}],["codestore.codes.length",{"_index":2203,"title":{},"content":{"122":{}},"tags":{}}],["codestore.codes.map((cod",{"_index":2152,"title":{},"content":{"121":{}},"tags":{}}],["codestoremodel",{"_index":2127,"title":{},"content":{"121":{}},"tags":{}}],["codestoresnapshotin",{"_index":2135,"title":{},"content":{"121":{}},"tags":{}}],["codestoresnapshotout",{"_index":2134,"title":{},"content":{"121":{}},"tags":{}}],["codetyp",{"_index":2175,"title":{},"content":{"122":{}},"tags":{}}],["collabor",{"_index":431,"title":{},"content":{"41":{}},"tags":{}}],["collect",{"_index":4,"title":{},"content":{"142":{},"143":{}},"tags":{}}],["coloc",{"_index":1637,"title":{},"content":{"137":{}},"tags":{}}],["color",{"_index":1017,"title":{},"content":{"80":{},"97":{},"128":{},"132":{},"133":{},"135":{},"136":{},"137":{},"160":{}},"tags":{}}],["color={colors.palette.neutral800",{"_index":1134,"title":{},"content":{"132":{},"136":{}},"tags":{}}],["color={colors.palette.primary400",{"_index":1533,"title":{},"content":{"136":{}},"tags":{}}],["color={focus",{"_index":1303,"title":{},"content":{"135":{}},"tags":{}}],["colors.background",{"_index":1247,"title":{},"content":{"80":{},"133":{},"135":{},"137":{}},"tags":{}}],["colors.palette.neutral100",{"_index":1258,"title":{},"content":{"133":{}},"tags":{}}],["colors.palette.neutral300",{"_index":1576,"title":{},"content":{"136":{}},"tags":{}}],["colors.palette.neutral600",{"_index":1632,"title":{},"content":{"136":{}},"tags":{}}],["colors.palette.primary100",{"_index":1579,"title":{},"content":{"136":{}},"tags":{}}],["colors.text",{"_index":1290,"title":{},"content":{"135":{}},"tags":{}}],["colors.textdim",{"_index":1572,"title":{},"content":{"136":{}},"tags":{}}],["colors.tint",{"_index":1187,"title":{},"content":{"132":{},"135":{},"136":{}},"tags":{}}],["colors.transpar",{"_index":1317,"title":{},"content":{"135":{}},"tags":{}}],["com.android.talkback/com.google.android.marvin.talkback.talkbackservic",{"_index":2666,"title":{},"content":{"112":{}},"tags":{}}],["com.google.android.marvin.talkback/com.google.android.marvin.talkback.talkbackservic",{"_index":2665,"title":{},"content":{"112":{}},"tags":{}}],["com.maestroapp",{"_index":1879,"title":{},"content":{"65":{},"66":{}},"tags":{}}],["combinereduc",{"_index":2312,"title":{},"content":{"81":{}},"tags":{}}],["come",{"_index":466,"title":{},"content":{"23":{},"41":{},"79":{},"119":{},"130":{}},"tags":{}}],["command",{"_index":336,"title":{},"content":{"40":{},"41":{},"45":{},"55":{},"64":{},"65":{},"73":{},"76":{},"90":{},"115":{},"121":{},"137":{},"138":{}},"tags":{}}],["commit",{"_index":283,"title":{},"content":{"39":{},"41":{},"73":{}},"tags":{}}],["commit_version_bump",{"_index":385,"title":{},"content":{"41":{}},"tags":{}}],["common",{"_index":6,"title":{"6":{}},"content":{"5":{},"142":{},"143":{}},"tags":{}}],["common.logout",{"_index":1225,"title":{},"content":{"133":{}},"tags":{}}],["commun",{"_index":12,"title":{"146":{}},"content":{"24":{},"135":{},"136":{},"142":{},"145":{},"146":{}},"tags":{}}],["companion",{"_index":1872,"title":{},"content":{"64":{}},"tags":{}}],["compat",{"_index":872,"title":{},"content":{"23":{},"50":{},"73":{},"103":{},"115":{}},"tags":{}}],["compil",{"_index":2041,"title":{},"content":{"55":{}},"tags":{}}],["compileropt",{"_index":975,"title":{},"content":{"127":{}},"tags":{}}],["compilesdkvers",{"_index":1992,"title":{},"content":{"73":{}},"tags":{}}],["complet",{"_index":116,"title":{},"content":{"1":{},"21":{},"24":{},"40":{},"64":{},"89":{},"90":{},"119":{},"150":{}},"tags":{}}],["compon",{"_index":157,"title":{"43":{},"45":{},"46":{},"97":{},"151":{},"157":{},"159":{}},"content":{"1":{},"7":{},"43":{},"45":{},"46":{},"48":{},"65":{},"66":{},"79":{},"80":{},"97":{},"105":{},"122":{},"127":{},"130":{},"132":{},"133":{},"136":{},"137":{},"149":{},"151":{},"157":{},"158":{},"159":{}},"tags":{}}],["components/selectfield",{"_index":2394,"title":{},"content":{"151":{},"156":{},"160":{}},"tags":{}}],["components/th",{"_index":2554,"title":{},"content":{"93":{}},"tags":{}}],["componenttyp",{"_index":1097,"title":{},"content":{"132":{},"136":{}},"tags":{}}],["componenttypetext",{"_index":161,"title":{},"content":{"1":{}},"tags":{}}],["fontscal",{"_index":154,"title":{},"content":{"1":{}},"tags":{}}],["fontsiz",{"_index":213,"title":{},"content":{"1":{},"135":{},"136":{},"137":{}},"tags":{}}],["fontsload",{"_index":1085,"title":{},"content":{"131":{}},"tags":{}}],["footer",{"_index":1536,"title":{},"content":{"136":{}},"tags":{}}],["footercompon",{"_index":1552,"title":{},"content":{"136":{},"159":{},"160":{}},"tags":{}}],["forc",{"_index":389,"title":{},"content":{"41":{}},"tags":{}}],["foreground",{"_index":863,"title":{},"content":{"23":{}},"tags":{}}],["forget",{"_index":2232,"title":{},"content":{"79":{}},"tags":{}}],["fork",{"_index":297,"title":{},"content":{"39":{},"73":{}},"tags":{}}],["form",{"_index":630,"title":{},"content":{"8":{},"130":{},"132":{}},"tags":{}}],["format",{"_index":611,"title":{},"content":{"7":{},"55":{},"128":{},"154":{}},"tags":{}}],["format\",\"format",{"_index":986,"title":{},"content":{"128":{}},"tags":{}}],["formatt",{"_index":2418,"title":{},"content":{"155":{}},"tags":{}}],["former",{"_index":665,"title":{},"content":{"30":{}},"tags":{}}],["formerli",{"_index":870,"title":{},"content":{"23":{}},"tags":{}}],["forward",{"_index":2029,"title":{},"content":{"49":{}},"tags":{}}],["forwardedref",{"_index":2597,"title":{},"content":{"105":{}},"tags":{}}],["forwardref",{"_index":2379,"title":{},"content":{"151":{},"156":{},"159":{},"160":{}},"tags":{}}],["forwardref(funct",{"_index":2386,"title":{},"content":{"151":{},"156":{},"159":{},"160":{}},"tags":{}}],["found",{"_index":333,"title":{},"content":{"40":{},"41":{},"76":{},"115":{}},"tags":{}}],["foundat",{"_index":888,"title":{},"content":{"24":{}},"tags":{}}],["free",{"_index":303,"title":{},"content":{"22":{},"39":{},"85":{},"137":{},"154":{}},"tags":{}}],["frontmatt",{"_index":1846,"title":{},"content":{"45":{}},"tags":{}}],["full",{"_index":944,"title":{"156":{}},"content":{"125":{},"139":{}},"tags":{}}],["fulli",{"_index":946,"title":{},"content":{"125":{}},"tags":{}}],["function",{"_index":50,"title":{},"content":{"24":{},"34":{},"60":{},"78":{},"81":{},"102":{},"105":{},"118":{},"120":{},"121":{},"122":{},"130":{},"132":{},"133":{},"136":{},"137":{},"144":{},"149":{},"151":{},"155":{},"156":{},"159":{},"160":{}},"tags":{}}],["futur",{"_index":1977,"title":{},"content":{"71":{}},"tags":{}}],["g",{"_index":787,"title":{},"content":{"17":{},"76":{},"85":{},"121":{},"137":{}},"tags":{}}],["galaxi",{"_index":2685,"title":{},"content":{"113":{}},"tags":{}}],["game",{"_index":1831,"title":{},"content":{"140":{}},"tags":{}}],["gboard",{"_index":2675,"title":{},"content":{"112":{}},"tags":{}}],["gem",{"_index":512,"title":{},"content":{"41":{}},"tags":{}}],["gener",{"_index":805,"title":{"43":{},"45":{},"46":{}},"content":{"20":{},"21":{},"43":{},"45":{},"46":{},"48":{},"72":{},"79":{},"88":{},"100":{},"101":{},"115":{},"118":{},"121":{}},"tags":{"43":{}}}],["generalapiproblem",{"_index":708,"title":{},"content":{"33":{}},"tags":{}}],["gestur",{"_index":2373,"title":{},"content":{"110":{},"112":{},"150":{}},"tags":{}}],["gesturehandlerrootview",{"_index":2349,"title":{},"content":{"81":{}},"tags":{}}],["get",{"_index":144,"title":{},"content":{"1":{},"21":{},"24":{},"79":{},"105":{},"137":{}},"tags":{}}],["getdefaultmiddlewar",{"_index":2324,"title":{},"content":{"81":{}},"tags":{}}],["getepisod",{"_index":704,"title":{},"content":{"33":{}},"tags":{}}],["gigant",{"_index":104,"title":{},"content":{"1":{}},"tags":{}}],["git",{"_index":491,"title":{},"content":{"41":{},"73":{},"115":{}},"tags":{}}],["github",{"_index":266,"title":{},"content":{"39":{},"41":{},"73":{},"115":{},"140":{}},"tags":{}}],["github/circleci",{"_index":434,"title":{},"content":{"41":{}},"tags":{}}],["github_token",{"_index":424,"title":{},"content":{"41":{}},"tags":{}}],["gitignor",{"_index":2004,"title":{},"content":{"73":{}},"tags":{}}],["given",{"_index":2630,"title":{},"content":{"115":{}},"tags":{}}],["global",{"_index":785,"title":{},"content":{"17":{},"85":{}},"tags":{}}],["global.nativefabricuimanag",{"_index":1592,"title":{},"content":{"136":{}},"tags":{}}],["go",{"_index":298,"title":{"100":{},"101":{},"102":{}},"content":{"6":{},"22":{},"33":{},"39":{},"41":{},"45":{},"49":{},"60":{},"64":{},"65":{},"66":{},"73":{},"85":{},"90":{},"100":{},"101":{},"102":{},"103":{},"104":{},"109":{},"110":{},"112":{},"137":{},"138":{},"140":{}},"tags":{}}],["goal",{"_index":74,"title":{},"content":{"25":{},"145":{}},"tags":{}}],["goback",{"_index":990,"title":{},"content":{"128":{},"138":{}},"tags":{}}],["goe",{"_index":1814,"title":{},"content":{"138":{}},"tags":{}}],["gonext",{"_index":1205,"title":{},"content":{"133":{}},"tags":{}}],["good",{"_index":544,"title":{"3":{},"6":{}},"content":{"8":{},"9":{},"79":{},"81":{},"85":{},"119":{}},"tags":{}}],["googl",{"_index":2676,"title":{},"content":{"112":{}},"tags":{}}],["gorhom/bottom",{"_index":2371,"title":{},"content":{"150":{},"158":{},"159":{},"160":{}},"tags":{}}],["grab",{"_index":733,"title":{},"content":{"34":{},"80":{}},"tags":{}}],["gradle.properti",{"_index":1994,"title":{},"content":{"73":{}},"tags":{}}],["gradlew",{"_index":2016,"title":{},"content":{"73":{}},"tags":{}}],["grant",{"_index":2115,"title":{},"content":{"120":{},"122":{}},"tags":{}}],["great",{"_index":261,"title":{},"content":{"8":{},"38":{},"67":{},"126":{}},"tags":{}}],["grey",{"_index":1497,"title":{},"content":{"136":{}},"tags":{}}],["groom",{"_index":518,"title":{},"content":{"41":{}},"tags":{}}],["ground",{"_index":1965,"title":{},"content":{"60":{}},"tags":{}}],["group",{"_index":562,"title":{},"content":{"5":{},"131":{},"135":{},"136":{}},"tags":{}}],["guess",{"_index":1195,"title":{},"content":{"105":{},"133":{}},"tags":{}}],["guid",{"_index":256,"title":{"72":{}},"content":{"16":{},"19":{},"24":{},"30":{},"44":{},"64":{},"72":{},"73":{},"78":{},"84":{},"100":{},"149":{},"154":{}},"tags":{"10":{},"32":{},"37":{},"70":{},"75":{},"115":{}}}],["handi",{"_index":189,"title":{},"content":{"1":{},"115":{}},"tags":{}}],["handl",{"_index":1057,"title":{},"content":{"54":{},"101":{},"105":{},"130":{},"137":{},"149":{}},"tags":{}}],["handlepresscard",{"_index":1523,"title":{},"content":{"136":{}},"tags":{}}],["handlepressfavorit",{"_index":1521,"title":{},"content":{"136":{}},"tags":{}}],["handler",{"_index":1803,"title":{},"content":{"138":{},"150":{},"151":{}},"tags":{}}],["handlescrol",{"_index":1677,"title":{},"content":{"137":{}},"tags":{}}],["handlescroll(findsectionindex",{"_index":1731,"title":{},"content":{"137":{}},"tags":{}}],["handlescroll?.(sectionindex",{"_index":1678,"title":{},"content":{"137":{}},"tags":{}}],["hang",{"_index":654,"title":{},"content":{"30":{}},"tags":{}}],["happen",{"_index":2344,"title":{},"content":{"81":{}},"tags":{}}],["hasn't",{"_index":2571,"title":{"105":{}},"content":{"105":{},"106":{}},"tags":{}}],["haven't",{"_index":1869,"title":{},"content":{"64":{},"105":{},"119":{}},"tags":{}}],["hawk",{"_index":2428,"title":{},"content":{"156":{},"160":{}},"tags":{}}],["head",{"_index":554,"title":{},"content":{"5":{},"22":{},"23":{},"121":{},"125":{},"132":{},"133":{},"136":{},"137":{}},"tags":{}}],["header",{"_index":559,"title":{},"content":{"5":{},"8":{},"22":{},"33":{},"34":{}},"tags":{}}],["headerbackallowfontsc",{"_index":179,"title":{},"content":{"1":{}},"tags":{}}],["headershown",{"_index":1091,"title":{},"content":{"131":{},"135":{}},"tags":{}}],["headertitleallowfontsc",{"_index":180,"title":{},"content":{"1":{}},"tags":{}}],["headingcompon",{"_index":1539,"title":{},"content":{"136":{}},"tags":{}}],["headingtx={episodestore.favoritesonli",{"_index":1459,"title":{},"content":{"136":{}},"tags":{}}],["hear",{"_index":87,"title":{},"content":{"110":{},"112":{},"147":{}},"tags":{}}],["heart",{"_index":1498,"title":{},"content":{"136":{}},"tags":{}}],["height",{"_index":1262,"title":{},"content":{"122":{},"133":{},"135":{},"136":{},"137":{}},"tags":{}}],["help",{"_index":40,"title":{},"content":{"41":{},"66":{},"93":{},"109":{},"110":{},"130":{},"131":{},"132":{},"135":{},"137":{},"143":{},"145":{}},"tags":{}}],["helper",{"_index":2252,"title":{},"content":{"80":{}},"tags":{}}],["helper=\"select",{"_index":2398,"title":{},"content":{"151":{},"156":{},"160":{}},"tags":{}}],["helper={error",{"_index":1159,"title":{},"content":{"132":{}},"tags":{}}],["helpers/withsetpropact",{"_index":2126,"title":{},"content":{"121":{}},"tags":{}}],["here",{"_index":312,"title":{},"content":{"24":{},"30":{},"40":{},"41":{},"43":{},"59":{},"66":{},"72":{},"76":{},"80":{},"96":{},"110":{},"119":{},"121":{},"127":{},"130":{},"131":{},"132":{},"135":{},"139":{},"140":{},"150":{}},"tags":{}}],["here'",{"_index":2296,"title":{},"content":{"80":{}},"tags":{}}],["hereapp",{"_index":1609,"title":{},"content":{"136":{}},"tags":{}}],["preset=\"bold\">fabr",{"_index":1620,"title":{},"content":{"136":{}},"tags":{}}],["preset=\"bold\">herm",{"_index":1617,"title":{},"content":{"136":{}},"tags":{}}],["preset=\"bold\">{item.name}(nul",{"_index":2599,"title":{},"content":{"105":{}},"tags":{}}],["react.usest",{"_index":198,"title":{},"content":{"1":{}},"tags":{}}],["react.usestate(fals",{"_index":1432,"title":{},"content":{"122":{},"136":{}},"tags":{}}],["react.usestate(tru",{"_index":169,"title":{},"content":{"1":{}},"tags":{}}],["react.usestate{section.description}{application.applicationid}{application.applicationname}{application.nativeapplicationversion}{application.nativebuildversion}{string(usingfabric)}{string(usinghermes)}{u}(nul",{"_index":2463,"title":{},"content":{"159":{},"160":{}},"tags":{}}],["useref>(nul",{"_index":1716,"title":{},"content":{"137":{}},"tags":{}}],["useref(nul",{"_index":1714,"title":{},"content":{"137":{}},"tags":{}}],["useref(nul",{"_index":1109,"title":{},"content":{"132":{}},"tags":{}}],["usesafeareainset",{"_index":1281,"title":{},"content":{"122":{},"135":{},"159":{},"160":{}},"tags":{}}],["usesafeareainsetsstyl",{"_index":1214,"title":{},"content":{"80":{},"133":{},"137":{}},"tags":{}}],["usesafeareainsetsstyle([\"bottom",{"_index":1228,"title":{},"content":{"133":{}},"tags":{}}],["usesafeareainsetsstyle([\"top",{"_index":1744,"title":{},"content":{"80":{},"137":{}},"tags":{}}],["useselector",{"_index":2257,"title":{},"content":{"80":{},"81":{}},"tags":{}}],["usesharedvalu",{"_index":1409,"title":{},"content":{"136":{}},"tags":{}}],["usesharedvalue(isfavorit",{"_index":1492,"title":{},"content":{"136":{}},"tags":{}}],["usest",{"_index":1101,"title":{},"content":{"132":{},"137":{}},"tags":{}}],["usestate(0",{"_index":1119,"title":{},"content":{"132":{}},"tags":{}}],["usestate(fals",{"_index":1116,"title":{},"content":{"132":{},"137":{}},"tags":{}}],["usestate(tru",{"_index":1113,"title":{},"content":{"132":{}},"tags":{}}],["usestate(array",{"_index":2484,"title":{},"content":{"160":{}},"tags":{}}],["withsetpropact",{"_index":2125,"title":{},"content":{"121":{}},"tags":{}}],["withspr",{"_index":1410,"title":{},"content":{"136":{}},"tags":{}}],["withspring(liked.valu",{"_index":1522,"title":{},"content":{"136":{}},"tags":{}}],["wizard",{"_index":2434,"title":{},"content":{"156":{},"160":{}},"tags":{}}],["won't",{"_index":634,"title":{},"content":{"8":{},"66":{},"73":{},"79":{}},"tags":{}}],["work",{"_index":69,"title":{"2":{},"6":{},"9":{},"15":{},"27":{},"31":{},"36":{},"42":{},"48":{},"56":{},"61":{},"69":{},"74":{},"77":{},"83":{},"91":{},"99":{},"104":{},"106":{},"114":{},"116":{},"123":{},"141":{},"148":{},"161":{}},"content":{"13":{},"35":{},"60":{},"72":{},"97":{},"112":{},"119":{},"145":{}},"tags":{}}],["workflow",{"_index":346,"title":{},"content":{"40":{},"41":{},"76":{},"84":{},"100":{},"102":{},"118":{}},"tags":{}}],["workflow=prebuild",{"_index":2086,"title":{},"content":{"119":{}},"tags":{}}],["working_directori",{"_index":319,"title":{},"content":{"40":{},"41":{},"76":{}},"tags":{}}],["workspac",{"_index":374,"title":{},"content":{"41":{}},"tags":{}}],["workstm",{"_index":1822,"title":{},"content":{"139":{}},"tags":{}}],["worri",{"_index":1685,"title":{},"content":{"137":{}},"tags":{}}],["wrap",{"_index":615,"title":{},"content":{"7":{},"80":{},"130":{},"131":{},"136":{},"151":{}},"tags":{}}],["wrapper",{"_index":1690,"title":{},"content":{"105":{},"137":{},"151":{}},"tags":{}}],["write",{"_index":259,"title":{},"content":{"30":{},"38":{},"41":{},"45":{},"55":{},"128":{}},"tags":{}}],["written",{"_index":31,"title":{},"content":{"118":{},"143":{},"145":{}},"tags":{}}],["wrote",{"_index":670,"title":{},"content":{"30":{}},"tags":{}}],["wwdc",{"_index":2636,"title":{},"content":{"109":{}},"tags":{}}],["x",{"_index":2608,"title":{},"content":{"105":{}},"tags":{}}],["x.name.tolowercas",{"_index":1723,"title":{},"content":{"137":{}},"tags":{}}],["x86_64",{"_index":2015,"title":{},"content":{"73":{}},"tags":{}}],["xcarg",{"_index":376,"title":{},"content":{"41":{}},"tags":{}}],["xcode",{"_index":482,"title":{},"content":{"41":{},"109":{}},"tags":{}}],["xcode_project",{"_index":367,"title":{},"content":{"41":{}},"tags":{}}],["xcodeproj",{"_index":386,"title":{},"content":{"41":{}},"tags":{}}],["y",{"_index":426,"title":{},"content":{"41":{},"105":{}},"tags":{}}],["yaml",{"_index":2355,"title":{"75":{},"76":{}},"content":{"77":{}},"tags":{}}],["yarn",{"_index":337,"title":{"115":{}},"content":{"12":{},"40":{},"41":{},"47":{},"50":{},"54":{},"59":{},"60":{},"65":{},"73":{},"76":{},"79":{},"80":{},"81":{},"87":{},"90":{},"94":{},"97":{},"115":{},"116":{},"119":{},"134":{},"150":{}},"tags":{"115":{}}}],["yarn.lock",{"_index":479,"title":{},"content":{"41":{}},"tags":{}}],["ye",{"_index":792,"title":{},"content":{"19":{},"52":{},"58":{},"78":{},"119":{},"126":{}},"tags":{}}],["you'll",{"_index":302,"title":{},"content":{"14":{},"17":{},"24":{},"39":{},"41":{},"64":{},"65":{},"73":{},"80":{},"85":{},"90":{},"93":{},"101":{},"109":{},"112":{},"131":{},"137":{}},"tags":{}}],["you'r",{"_index":54,"title":{},"content":{"5":{},"17":{},"23":{},"65":{},"66":{},"80":{},"85":{},"112":{},"121":{},"130":{},"132":{},"144":{},"150":{}},"tags":{}}],["you'v",{"_index":875,"title":{},"content":{"23":{}},"tags":{}}],["you:tripl",{"_index":2642,"title":{},"content":{"110":{}},"tags":{}}],["your",{"_index":2559,"title":{},"content":{"95":{}},"tags":{}}],["yourproject",{"_index":366,"title":{},"content":{"41":{}},"tags":{}}],["yourproject.log",{"_index":543,"title":{},"content":{"41":{}},"tags":{}}],["yourproject.xcworkspac",{"_index":375,"title":{},"content":{"41":{}},"tags":{}}],["yourself",{"_index":529,"title":{},"content":{"41":{}},"tags":{}}],["zxvf",{"_index":2523,"title":{},"content":{"90":{}},"tags":{}}]],"pipeline":["stemmer"]}} \ No newline at end of file diff --git a/sitemap.xml b/sitemap.xml index 4b5c4a83..b02c65e1 100644 --- a/sitemap.xml +++ b/sitemap.xml @@ -1 +1 @@ -https://infinitered.github.io/docs/tagsweekly0.5https://infinitered.github.io/docs/tags/accessibilityweekly0.5https://infinitered.github.io/docs/tags/androidweekly0.5https://infinitered.github.io/docs/tags/apisauceweekly0.5https://infinitered.github.io/docs/tags/async-storageweekly0.5https://infinitered.github.io/docs/tags/authenticationweekly0.5https://infinitered.github.io/docs/tags/babelweekly0.5https://infinitered.github.io/docs/tags/ci-cdweekly0.5https://infinitered.github.io/docs/tags/debugweekly0.5https://infinitered.github.io/docs/tags/dependenciesweekly0.5https://infinitered.github.io/docs/tags/eas-updateweekly0.5https://infinitered.github.io/docs/tags/environment-variablesweekly0.5https://infinitered.github.io/docs/tags/expoweekly0.5https://infinitered.github.io/docs/tags/expo-dev-clientweekly0.5https://infinitered.github.io/docs/tags/expo-updatesweekly0.5https://infinitered.github.io/docs/tags/flat-listweekly0.5https://infinitered.github.io/docs/tags/generatorweekly0.5https://infinitered.github.io/docs/tags/guideweekly0.5https://infinitered.github.io/docs/tags/i-osweekly0.5https://infinitered.github.io/docs/tags/introweekly0.5https://infinitered.github.io/docs/tags/maestroweekly0.5https://infinitered.github.io/docs/tags/mmkvweekly0.5https://infinitered.github.io/docs/tags/mob-xweekly0.5https://infinitered.github.io/docs/tags/react-native-vision-cameraweekly0.5https://infinitered.github.io/docs/tags/reduxweekly0.5https://infinitered.github.io/docs/tags/scroll-toweekly0.5https://infinitered.github.io/docs/tags/section-listweekly0.5https://infinitered.github.io/docs/tags/select-fieldweekly0.5https://infinitered.github.io/docs/tags/state-managementweekly0.5https://infinitered.github.io/docs/tags/testingweekly0.5https://infinitered.github.io/docs/tags/text-fieldweekly0.5https://infinitered.github.io/docs/tags/type-scriptweekly0.5https://infinitered.github.io/docs/tags/uiweekly0.5https://infinitered.github.io/docs/tags/vision-cameraweekly0.5https://infinitered.github.io/docs/tags/yarnweekly0.5https://infinitered.github.io/docs/introweekly0.5https://infinitered.github.io/docs/recipes/AccessibilityFontSizesweekly0.5https://infinitered.github.io/docs/recipes/CircleCIRNSetupweekly0.5https://infinitered.github.io/docs/recipes/CreatingGreateExperienceForScreenReadersweekly0.5https://infinitered.github.io/docs/recipes/DetoxIntroweekly0.5https://infinitered.github.io/docs/recipes/DistributingAuthTokenToAPIweekly0.5https://infinitered.github.io/docs/recipes/EASUpdateweekly0.5https://infinitered.github.io/docs/recipes/EnvironmentVariablesweekly0.5https://infinitered.github.io/docs/recipes/GeneratorComponentTestsweekly0.5https://infinitered.github.io/docs/recipes/MaestroSetupweekly0.5https://infinitered.github.io/docs/recipes/MigratingToMMKVweekly0.5https://infinitered.github.io/docs/recipes/PatchingBuildingAndroidweekly0.5https://infinitered.github.io/docs/recipes/PristineExpoProjectweekly0.5https://infinitered.github.io/docs/recipes/ReactNativeVisionCameraweekly0.5https://infinitered.github.io/docs/recipes/Reduxweekly0.5https://infinitered.github.io/docs/recipes/SampleYAMLCircleCIweekly0.5https://infinitered.github.io/docs/recipes/SelectFieldWithBottomSheetweekly0.5https://infinitered.github.io/docs/recipes/StayingWithExpoweekly0.5https://infinitered.github.io/docs/recipes/SwitchBetweenExpoGoCNGweekly0.5https://infinitered.github.io/docs/recipes/TypeScriptBaseURLweekly0.5https://infinitered.github.io/docs/recipes/UnrenderedItemInScrollViewweekly0.5https://infinitered.github.io/docs/recipes/UpdatingDependenciesweekly0.5https://infinitered.github.io/docs/recipes/UsingScreenReadersweekly0.5https://infinitered.github.io/weekly0.5 \ No newline at end of file +https://infinitered.github.io/docs/tagsweekly0.5https://infinitered.github.io/docs/tags/accessibilityweekly0.5https://infinitered.github.io/docs/tags/androidweekly0.5https://infinitered.github.io/docs/tags/apisauceweekly0.5https://infinitered.github.io/docs/tags/async-storageweekly0.5https://infinitered.github.io/docs/tags/authenticationweekly0.5https://infinitered.github.io/docs/tags/babelweekly0.5https://infinitered.github.io/docs/tags/ci-cdweekly0.5https://infinitered.github.io/docs/tags/debugweekly0.5https://infinitered.github.io/docs/tags/dependenciesweekly0.5https://infinitered.github.io/docs/tags/eas-updateweekly0.5https://infinitered.github.io/docs/tags/environment-variablesweekly0.5https://infinitered.github.io/docs/tags/expoweekly0.5https://infinitered.github.io/docs/tags/expo-dev-clientweekly0.5https://infinitered.github.io/docs/tags/expo-routerweekly0.5https://infinitered.github.io/docs/tags/expo-updatesweekly0.5https://infinitered.github.io/docs/tags/flat-listweekly0.5https://infinitered.github.io/docs/tags/generatorweekly0.5https://infinitered.github.io/docs/tags/guideweekly0.5https://infinitered.github.io/docs/tags/i-osweekly0.5https://infinitered.github.io/docs/tags/introweekly0.5https://infinitered.github.io/docs/tags/maestroweekly0.5https://infinitered.github.io/docs/tags/mmkvweekly0.5https://infinitered.github.io/docs/tags/mob-xweekly0.5https://infinitered.github.io/docs/tags/react-native-vision-cameraweekly0.5https://infinitered.github.io/docs/tags/react-navigationweekly0.5https://infinitered.github.io/docs/tags/reduxweekly0.5https://infinitered.github.io/docs/tags/scroll-toweekly0.5https://infinitered.github.io/docs/tags/section-listweekly0.5https://infinitered.github.io/docs/tags/select-fieldweekly0.5https://infinitered.github.io/docs/tags/state-managementweekly0.5https://infinitered.github.io/docs/tags/testingweekly0.5https://infinitered.github.io/docs/tags/text-fieldweekly0.5https://infinitered.github.io/docs/tags/type-scriptweekly0.5https://infinitered.github.io/docs/tags/uiweekly0.5https://infinitered.github.io/docs/tags/vision-cameraweekly0.5https://infinitered.github.io/docs/tags/yarnweekly0.5https://infinitered.github.io/docs/introweekly0.5https://infinitered.github.io/docs/recipes/AccessibilityFontSizesweekly0.5https://infinitered.github.io/docs/recipes/CircleCIRNSetupweekly0.5https://infinitered.github.io/docs/recipes/CreatingGreateExperienceForScreenReadersweekly0.5https://infinitered.github.io/docs/recipes/DetoxIntroweekly0.5https://infinitered.github.io/docs/recipes/DistributingAuthTokenToAPIweekly0.5https://infinitered.github.io/docs/recipes/EASUpdateweekly0.5https://infinitered.github.io/docs/recipes/EnvironmentVariablesweekly0.5https://infinitered.github.io/docs/recipes/ExpoRouterweekly0.5https://infinitered.github.io/docs/recipes/GeneratorComponentTestsweekly0.5https://infinitered.github.io/docs/recipes/MaestroSetupweekly0.5https://infinitered.github.io/docs/recipes/MigratingToMMKVweekly0.5https://infinitered.github.io/docs/recipes/PatchingBuildingAndroidweekly0.5https://infinitered.github.io/docs/recipes/PristineExpoProjectweekly0.5https://infinitered.github.io/docs/recipes/ReactNativeVisionCameraweekly0.5https://infinitered.github.io/docs/recipes/Reduxweekly0.5https://infinitered.github.io/docs/recipes/SampleYAMLCircleCIweekly0.5https://infinitered.github.io/docs/recipes/SelectFieldWithBottomSheetweekly0.5https://infinitered.github.io/docs/recipes/StayingWithExpoweekly0.5https://infinitered.github.io/docs/recipes/SwitchBetweenExpoGoCNGweekly0.5https://infinitered.github.io/docs/recipes/TypeScriptBaseURLweekly0.5https://infinitered.github.io/docs/recipes/UnrenderedItemInScrollViewweekly0.5https://infinitered.github.io/docs/recipes/UpdatingDependenciesweekly0.5https://infinitered.github.io/docs/recipes/UsingScreenReadersweekly0.5https://infinitered.github.io/weekly0.5 \ No newline at end of file