feat: 🎸 Fix image load and typescript errors (#570)
* Update Cocoapods version * Use new api GetRequestHeaders to get headers * Remove warnings of missing colors and brushes * Fix typing errors * Change affected main branch to main * Remove unused feature toggle * Add dummy login checker to remove using any
This commit is contained in:
parent
aea848f66a
commit
933a8840a3
|
@ -1,4 +1,4 @@
|
|||
import { CalendarItem } from '@skolplattformen/api-skolplattformen'
|
||||
import { CalendarItem } from '@skolplattformen/api'
|
||||
import { useCalendar } from '@skolplattformen/hooks'
|
||||
import {
|
||||
Divider,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { Child } from '@skolplattformen/api-skolplattformen'
|
||||
import { Child } from '@skolplattformen/api'
|
||||
import React, { createContext, useContext } from 'react'
|
||||
|
||||
interface ChildProviderProps {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* eslint-disable react-native-a11y/has-accessibility-hint */
|
||||
import { useNavigation } from '@react-navigation/native'
|
||||
import { StackNavigationProp } from '@react-navigation/stack'
|
||||
import { Child } from '@skolplattformen/api-skolplattformen'
|
||||
import { Child } from '@skolplattformen/api'
|
||||
import {
|
||||
useCalendar,
|
||||
useClassmates,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { useNavigation } from '@react-navigation/core'
|
||||
import { Child } from '@skolplattformen/api-skolplattformen'
|
||||
import { Child } from '@skolplattformen/api'
|
||||
import { useApi, useChildList } from '@skolplattformen/hooks'
|
||||
import {
|
||||
Button,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { Classmate } from '@skolplattformen/api-skolplattformen'
|
||||
import { Classmate } from '@skolplattformen/api'
|
||||
import { useClassmates } from '@skolplattformen/hooks'
|
||||
import {
|
||||
Divider,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* eslint-disable react-native-a11y/has-accessibility-hint */
|
||||
import { Classmate } from '@skolplattformen/api-skolplattformen'
|
||||
import { Classmate } from '@skolplattformen/api'
|
||||
import {
|
||||
Button,
|
||||
MenuGroup,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { Child } from '@skolplattformen/api-skolplattformen'
|
||||
import { Child } from '@skolplattformen/api'
|
||||
import { useTimetable } from '@skolplattformen/hooks'
|
||||
import { StyleService, Text, useStyleSheet } from '@ui-kitten/components'
|
||||
import moment, { Moment } from 'moment'
|
||||
|
|
|
@ -31,7 +31,7 @@ export const Image = ({
|
|||
resizeMode = 'contain',
|
||||
}: ImageProps) => {
|
||||
const { api } = useApi()
|
||||
const [headers, setHeaders] = useState()
|
||||
const [headers, setHeaders] = useState<{ [index: string]: string }>()
|
||||
const { width: windowWidth } = useWindowDimensions()
|
||||
const [dimensions, setDimensions] = useState({ width: 0, height: 0 })
|
||||
|
||||
|
@ -40,7 +40,7 @@ export const Image = ({
|
|||
const prefetchImageInformation = useCallback(
|
||||
async (url: string) => {
|
||||
if (!url) return
|
||||
const { headers: newHeaders } = await api.getSession(url)
|
||||
const newHeaders = await api.getSessionHeaders(url)
|
||||
|
||||
console.log('[IMAGE] Getting image dimensions with headers', {
|
||||
debugImageName,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { MenuItem } from '@skolplattformen/api-skolplattformen'
|
||||
import { MenuItem } from '@skolplattformen/api'
|
||||
import { useMenu } from '@skolplattformen/hooks'
|
||||
import {
|
||||
Divider,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { MenuItem } from '@skolplattformen/api-skolplattformen'
|
||||
import { MenuItem } from '@skolplattformen/api'
|
||||
import { StyleService, Text, useStyleSheet } from '@ui-kitten/components'
|
||||
import React from 'react'
|
||||
import { View } from 'react-native'
|
||||
|
|
|
@ -20,12 +20,12 @@ export const ModalWebView = ({
|
|||
const [modalVisible, setModalVisible] = React.useState(true)
|
||||
const { api } = useApi()
|
||||
const [title, setTitle] = React.useState('...')
|
||||
const [headers, setHeaders] = useState()
|
||||
const [headers, setHeaders] = useState<{ [index: string]: string }>()
|
||||
|
||||
useEffect(() => {
|
||||
const getHeaders = async (urlToGetSessionFor: string) => {
|
||||
if (sharedCookiesEnabled) return
|
||||
const { headers: newHeaders } = await api.getSession(urlToGetSessionFor)
|
||||
const newHeaders = await api.getSessionHeaders(urlToGetSessionFor)
|
||||
setHeaders(newHeaders)
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ import { NavigationContainer } from '@react-navigation/native'
|
|||
import {
|
||||
Child as ChildType,
|
||||
NewsItem as NewsItemType,
|
||||
} from '@skolplattformen/api-skolplattformen'
|
||||
} from '@skolplattformen/api'
|
||||
import { useApi } from '@skolplattformen/hooks'
|
||||
import { useTheme } from '@ui-kitten/components'
|
||||
import { Library } from 'libraries.json'
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { useNavigation } from '@react-navigation/native'
|
||||
import { StackNavigationProp } from '@react-navigation/stack'
|
||||
import { NewsItem } from '@skolplattformen/api-skolplattformen'
|
||||
import { NewsItem } from '@skolplattformen/api'
|
||||
import { StyleService, useStyleSheet } from '@ui-kitten/components'
|
||||
import moment from 'moment'
|
||||
import React, { ReactNode } from 'react'
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { Notification as NotificationType } from '@skolplattformen/api-skolplattformen'
|
||||
import { Notification as NotificationType } from '@skolplattformen/api'
|
||||
import { StyleService, Text, useStyleSheet } from '@ui-kitten/components'
|
||||
import moment from 'moment'
|
||||
import React from 'react'
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { CalendarItem } from '@skolplattformen/api-skolplattformen'
|
||||
import { CalendarItem } from '@skolplattformen/api'
|
||||
import { Button, MenuItem, OverflowMenu, Text } from '@ui-kitten/components'
|
||||
import React from 'react'
|
||||
import RNCalendarEvents from 'react-native-calendar-events'
|
||||
|
|
|
@ -1,8 +1,4 @@
|
|||
import {
|
||||
Child,
|
||||
MenuItem,
|
||||
TimetableEntry,
|
||||
} from '@skolplattformen/api-skolplattformen'
|
||||
import { Child, MenuItem, TimetableEntry } from '@skolplattformen/api'
|
||||
import { useMenu, useTimetable } from '@skolplattformen/hooks'
|
||||
import {
|
||||
List,
|
||||
|
|
|
@ -2,8 +2,9 @@ import { Features, FeatureType } from '@skolplattformen/api'
|
|||
import React from 'react'
|
||||
|
||||
export const FeatureFlagsContext = React.createContext<Features>({
|
||||
LOGIN_BANK_ID_SAME_DEVICE: false,
|
||||
LOGIN_BANK_ID_SAME_DEVICE_WITHOUT_ID: true,
|
||||
FOOD_MENU: false,
|
||||
CLASS_LIST: true,
|
||||
})
|
||||
|
||||
interface Props {
|
||||
|
|
|
@ -16,7 +16,7 @@ export const SchoolPlatformProvider: React.FC = ({ children }) => {
|
|||
'currentSchoolPlatform'
|
||||
)
|
||||
|
||||
const changeSchoolPlatform = (platform: string) => {
|
||||
const changeSchoolPlatform = (platform) => {
|
||||
setCurrentSchoolPlatform(platform)
|
||||
}
|
||||
|
||||
|
|
|
@ -10,13 +10,13 @@ export const schoolPlatforms = [
|
|||
{
|
||||
id: 'stockholm-skolplattformen',
|
||||
displayName: 'Stockholm stad (Skolplattformen)',
|
||||
api: initSkolplattformen(fetch, CookieManager),
|
||||
api: initSkolplattformen(fetch as any, CookieManager),
|
||||
features: featuresSkolPlattformen,
|
||||
},
|
||||
{
|
||||
id: 'goteborg-hjarntorget',
|
||||
displayName: 'Göteborg stad (Hjärntorget)',
|
||||
api: initHjarntorget(fetch, CookieManager),
|
||||
api: initHjarntorget(fetch as any, CookieManager),
|
||||
features: featuresHjarntorget,
|
||||
},
|
||||
]
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import AsyncStorage from '@react-native-async-storage/async-storage'
|
||||
import { User } from '@skolplattformen/api-skolplattformen'
|
||||
import { User } from '@skolplattformen/api'
|
||||
import { act, renderHook } from '@testing-library/react-hooks'
|
||||
import usePersonalStorage from '../usePersonalStorage'
|
||||
|
||||
|
|
|
@ -669,4 +669,4 @@ SPEC CHECKSUMS:
|
|||
|
||||
PODFILE CHECKSUM: 85f5a2dfa1de342b427eecb6e9652410ad153247
|
||||
|
||||
COCOAPODS: 1.10.1
|
||||
COCOAPODS: 1.11.2
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import AsyncStorage from '@react-native-async-storage/async-storage'
|
||||
import { User } from '@skolplattformen/api-skolplattformen'
|
||||
import { User } from '@skolplattformen/api'
|
||||
import AppStorage from '../appStorage'
|
||||
|
||||
beforeEach(() => {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import AsyncStorage from '@react-native-async-storage/async-storage'
|
||||
import { User } from '@skolplattformen/api-skolplattformen'
|
||||
import { User } from '@skolplattformen/api'
|
||||
|
||||
export default class AppStorage {
|
||||
static settingsStorageKeyPrefix = 'appsetting_'
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { Guardian } from '@skolplattformen/api-skolplattformen'
|
||||
import { Guardian } from '@skolplattformen/api'
|
||||
|
||||
export const studentName = (name?: string) => name?.replace(/\s?\(\w+\)$/, '')
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { NewsItem } from '@skolplattformen/api-skolplattformen'
|
||||
import { NewsItem } from '@skolplattformen/api'
|
||||
import { useNews } from '@skolplattformen/hooks'
|
||||
import { MatchData, Searcher } from 'fast-fuzzy'
|
||||
import React, { ReactNode, useMemo } from 'react'
|
||||
|
|
|
@ -5,6 +5,7 @@ import { EvaIconsPack } from '@ui-kitten/eva-icons'
|
|||
import React, { ReactElement } from 'react'
|
||||
import { LanguageProvider } from '../context/language/languageContext'
|
||||
import { translations } from './translation'
|
||||
import { lightTheme } from '../design/themes'
|
||||
|
||||
export const render = (
|
||||
ui: ReactElement<any, string>,
|
||||
|
@ -14,7 +15,7 @@ export const render = (
|
|||
return (
|
||||
<>
|
||||
<IconRegistry icons={EvaIconsPack} />
|
||||
<ApplicationProvider {...eva} theme={eva.light}>
|
||||
<ApplicationProvider {...eva} theme={lightTheme}>
|
||||
<LanguageProvider
|
||||
cache={false}
|
||||
data={translations}
|
||||
|
|
|
@ -5,6 +5,7 @@ import {
|
|||
Classmate,
|
||||
CookieManager,
|
||||
EtjanstChild,
|
||||
Fetch,
|
||||
Fetcher,
|
||||
FetcherOptions,
|
||||
LoginStatusChecker,
|
||||
|
@ -24,7 +25,7 @@ import { decode } from 'he'
|
|||
import { DateTime, FixedOffsetZone } from 'luxon'
|
||||
import * as html from 'node-html-parser'
|
||||
import { fakeFetcher } from './fake/fakeFetcher'
|
||||
import { checkStatus } from './loginStatus'
|
||||
import { checkStatus, DummyStatusChecker } from './loginStatus'
|
||||
import { extractMvghostRequestBody, parseCalendarItem } from './parse/parsers'
|
||||
import {
|
||||
beginBankIdUrl,
|
||||
|
@ -84,7 +85,7 @@ export class ApiHjarntorget extends EventEmitter implements Api {
|
|||
}
|
||||
|
||||
constructor(
|
||||
fetch: typeof global.fetch,
|
||||
fetch: Fetch,
|
||||
cookieManager: CookieManager,
|
||||
options?: FetcherOptions
|
||||
) {
|
||||
|
@ -138,6 +139,13 @@ export class ApiHjarntorget extends EventEmitter implements Api {
|
|||
return this.personalNumber
|
||||
}
|
||||
|
||||
public async getSessionHeaders(url: string): Promise<{ [index: string]: string }> {
|
||||
const cookie = await this.cookieManager.getCookieString(url)
|
||||
return {
|
||||
cookie,
|
||||
}
|
||||
}
|
||||
|
||||
async setSessionCookie(sessionCookie: string): Promise<void> {
|
||||
await this.fetch('login-cookie', hjarntorgetUrl, {
|
||||
headers: {
|
||||
|
@ -490,13 +498,13 @@ export class ApiHjarntorget extends EventEmitter implements Api {
|
|||
|
||||
if((beginLoginRedirectResponse as any).url.endsWith("startPage.do")) {
|
||||
// already logged in!
|
||||
const emitter = new EventEmitter()
|
||||
const emitter = new DummyStatusChecker()
|
||||
setTimeout(() => {
|
||||
this.isLoggedIn = true
|
||||
emitter.emit('OK')
|
||||
this.emit('login')
|
||||
}, 50)
|
||||
return emitter;
|
||||
return emitter as LoginStatusChecker;
|
||||
}
|
||||
|
||||
console.log('prepping??? shibboleth')
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -28,10 +28,9 @@ const fetchMappings: { [name:string]: () => Response} = {
|
|||
'event-role-members-24-821': eventRoleMembers24,
|
||||
'calendars': calendars,
|
||||
'calendar-14241345': calendar_14241345,
|
||||
|
||||
}
|
||||
|
||||
export const fakeFetcher: Fetcher = (name: string, url: string, init?: any): Promise<Response> => {
|
||||
const responder = fetchMappings[name] ?? (() => {throw new Error("Request not faked for name: " + name)})
|
||||
return Promise.resolve(responder());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ import {
|
|||
pollStatusUrl,
|
||||
} from './routes'
|
||||
|
||||
export class HjarntorgetChecker extends EventEmitter {
|
||||
export class HjarntorgetChecker extends EventEmitter implements LoginStatusChecker {
|
||||
private fetcher: Fetcher
|
||||
|
||||
private basePollingUrl: string
|
||||
|
@ -120,3 +120,10 @@ export const checkStatus = (
|
|||
fetch: Fetcher,
|
||||
basePollingUrl: string
|
||||
): LoginStatusChecker => new HjarntorgetChecker(fetch, basePollingUrl)
|
||||
|
||||
export class DummyStatusChecker extends EventEmitter implements LoginStatusChecker {
|
||||
token = ""
|
||||
async cancel(): Promise<void> {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ the concrete implementation of fetch and cookie handler must be injected.
|
|||
#### react-native
|
||||
|
||||
```javascript
|
||||
import init from '@skolplattformen/api-skolplattformen'
|
||||
import init from '@skolplattformen/api'
|
||||
import CookieManager from '@react-native-cookies/cookies'
|
||||
|
||||
const api = init(fetch, () => CookieManager.clearAll())
|
||||
|
@ -25,7 +25,7 @@ const api = init(fetch, () => CookieManager.clearAll())
|
|||
#### node
|
||||
|
||||
```javascript
|
||||
import init from '@skolplattformen/api-skolplattformen'
|
||||
import init from '@skolplattformen/api'
|
||||
import nodeFetch from 'node-fetch'
|
||||
import fetchCookie from 'fetch-cookie/node-fetch'
|
||||
import { CookieJar } from 'tough-cookie'
|
||||
|
|
|
@ -28,7 +28,7 @@ import { decode } from 'he'
|
|||
import { DateTime } from 'luxon'
|
||||
import * as html from 'node-html-parser'
|
||||
import * as fake from './fakeData'
|
||||
import { checkStatus } from './loginStatusChecker'
|
||||
import { checkStatus, DummyStatusChecker } from './loginStatusChecker'
|
||||
import * as parse from './parse/index'
|
||||
import * as routes from './routes'
|
||||
|
||||
|
@ -94,6 +94,16 @@ export class ApiSkolplattformen extends EventEmitter implements Api {
|
|||
}
|
||||
}
|
||||
|
||||
public async getSessionHeaders(url: string): Promise<{ [index: string]: string }> {
|
||||
const init = this.getRequestInit()
|
||||
const cookie = await this.cookieManager.getCookieString(url)
|
||||
return {
|
||||
...init.headers,
|
||||
cookie,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public async getSession(
|
||||
url: string,
|
||||
options?: RequestInit
|
||||
|
@ -203,8 +213,7 @@ export class ApiSkolplattformen extends EventEmitter implements Api {
|
|||
this.emit('login')
|
||||
}, 50)
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const emitter: any = new EventEmitter()
|
||||
const emitter = new DummyStatusChecker()
|
||||
emitter.token = 'fake'
|
||||
return emitter
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ import { EventEmitter } from 'events';
|
|||
import { loginStatus } from './routes';
|
||||
import { AuthTicket, Fetcher, LoginStatusChecker } from '@skolplattformen/api';
|
||||
|
||||
export class Checker extends EventEmitter {
|
||||
export class Checker extends EventEmitter implements LoginStatusChecker {
|
||||
public token: string;
|
||||
|
||||
private fetcher: Fetcher;
|
||||
|
@ -41,3 +41,10 @@ export const checkStatus = (
|
|||
fetch: Fetcher,
|
||||
ticket: AuthTicket
|
||||
): LoginStatusChecker => new Checker(fetch, ticket)
|
||||
|
||||
export class DummyStatusChecker extends EventEmitter implements LoginStatusChecker {
|
||||
token = ""
|
||||
async cancel(): Promise<void> {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ export interface Api extends EventEmitter {
|
|||
getPersonalNumber(): string | undefined
|
||||
login(personalNumber?: string): Promise<LoginStatusChecker>
|
||||
setSessionCookie(sessionCookie: string): Promise<void>
|
||||
getSessionHeaders(url: string): Promise<{ [index: string]: string }>
|
||||
getUser(): Promise<User>
|
||||
getChildren(): Promise<EtjanstChild[]>
|
||||
getCalendar(child: EtjanstChild): Promise<CalendarItem[]>
|
||||
|
|
|
@ -18,7 +18,7 @@ In order to use api hooks, you must wrap your app in an ApiProvider
|
|||
```javascript
|
||||
import React from 'react'
|
||||
import { ApiProvider } from '@skolplattformen/hooks'
|
||||
import init from '@skolplattformen/api-skolplattformen'
|
||||
import init from '@skolplattformen/api-skolplattformet'
|
||||
import { CookieManager } from '@react-native-cookies/cookies'
|
||||
import AsyncStorage from '@react-native-async-storage/async-storage'
|
||||
import { RootComponent } from './components/root'
|
||||
|
|
|
@ -107,7 +107,7 @@ const hook = <T>(
|
|||
|
||||
if (newState.error) {
|
||||
const description = `Error getting ${entityName} from API`
|
||||
reporter.error(newState.error, description)
|
||||
reporter.error && reporter.error(newState.error, description)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue