@@ -21,7 +21,15 @@ import {
2121 isDocumentReference
2222} from "./firebase-common" ;
2323import * as firebaseFunctions from "./functions/functions" ;
24+ < < < << << HEAD
2425import * as firebaseMessaging from "./messaging/messaging" ;
26+ === === =
27+ import * as appModule from "tns-core-modules/application" ;
28+ import { AndroidActivityResultEventData } from "tns-core-modules/application" ;
29+ import { ad as AndroidUtils } from "tns-core-modules/utils/utils" ;
30+ import lazy from "tns-core-modules/utils/lazy" ;
31+ import { firestore , User , OnDisconnect as OnDisconnectBase , DataSnapshot , Query as QueryBase } from "./firebase" ;
32+ >>> >>> > [ query ] - Rework firebaseWebApi queries to allow chaining of filters . Android implementation
2533
2634declare const com : any ;
2735const gmsAds = ( < any > com . google . android . gms ) . ads ;
@@ -1421,22 +1429,22 @@ firebase.keepInSync = (path, switchOn) => {
14211429} ;
14221430
14231431firebase . _addObservers = ( to , updateCallback ) => {
1424- const listener = new com . google . firebase . database . ChildEventListener ( {
1425- onCancelled : databaseError => {
1432+ const listener : com . google . firebase . database . ChildEventListener = new com . google . firebase . database . ChildEventListener ( {
1433+ onCancelled : ( databaseError : com . google . firebase . database . DatabaseError ) => {
14261434 updateCallback ( {
14271435 error : databaseError . getMessage ( )
14281436 } ) ;
14291437 } ,
1430- onChildAdded : ( snapshot , previousChildKey ) => {
1438+ onChildAdded : ( snapshot : com . google . firebase . database . DataSnapshot , previousChildKey : string ) => {
14311439 updateCallback ( firebase . getCallbackData ( 'ChildAdded' , snapshot ) ) ;
14321440 } ,
1433- onChildRemoved : snapshot => {
1441+ onChildRemoved : ( snapshot : com . google . firebase . database . DataSnapshot ) => {
14341442 updateCallback ( firebase . getCallbackData ( 'ChildRemoved' , snapshot ) ) ;
14351443 } ,
1436- onChildChanged : ( snapshot , previousChildKey ) => {
1444+ onChildChanged : ( snapshot : com . google . firebase . database . DataSnapshot , previousChildKey : string ) => {
14371445 updateCallback ( firebase . getCallbackData ( 'ChildChanged' , snapshot ) ) ;
14381446 } ,
1439- onChildMoved : ( snapshot , previousChildKey ) => {
1447+ onChildMoved : ( snapshot : com . google . firebase . database . DataSnapshot , previousChildKey : string ) => {
14401448 updateCallback ( firebase . getCallbackData ( 'ChildMoved' , snapshot ) ) ;
14411449 }
14421450 } ) ;
@@ -1622,8 +1630,218 @@ firebase.update = (path, val) => {
16221630 } ) ;
16231631} ;
16241632
1633+ < < < << << HEAD
16251634firebase . query = ( updateCallback : ( data : FBDataSingleEvent | FBErrorData ) => void , path : string , options : QueryOptions ) : Promise < any > => {
16261635 return new Promise < any > ( ( resolve , reject ) => {
1636+ = === ===
1637+ firebase . webQuery = ( path : string ) : QueryBase => {
1638+ if ( ! firebase . initialized ) {
1639+ console . error ( "Please run firebase.init() before firebase.query()" ) ;
1640+ throw new Error ( "FirebaseApp is not initialized. Make sure you run firebase.init() first" ) ;
1641+ }
1642+ const dbRef : com . google . firebase . database . DatabaseReference = firebase . instance . child ( path ) ;
1643+ return new Query ( dbRef , path ) ;
1644+ } ;
1645+
1646+ class Query implements QueryBase {
1647+ private query : com . google . firebase . database . Query ; // Keep track of internal query state allowing us to chain filter/range/limit
1648+ private static eventListenerMap : Map < string , Array < any > > = new Map ( ) ; // A map to keep track all all the listeners attached for the specified eventType
1649+
1650+ constructor ( private dbRef : com . google . firebase . database . DatabaseReference , private path : string ) { }
1651+
1652+ on ( eventType : string , callback : ( a : any , b ?: string ) => any ) : Promise < any > {
1653+ const onValueEvent = result => {
1654+ if ( result . error ) {
1655+ callback ( result ) ; // CAREFUL before we were calling result.error!
1656+ } else {
1657+ callback ( {
1658+ key : result . key ,
1659+ val : ( ) => result . value ,
1660+ exists : ( ) => ! ! result . value
1661+ } ) ;
1662+ }
1663+ } ;
1664+ return new Promise ( ( resolve , reject ) => {
1665+ try {
1666+ if ( firebase . instance === null ) {
1667+ reject ( "Run init() first!" ) ;
1668+ return ;
1669+ }
1670+ const listener = this . createEventListener ( eventType , onValueEvent ) ;
1671+ if ( ! this . query ) this . query = this . dbRef ; // Need this when calling on() without doing a sort as this.query is undefined
1672+
1673+ if ( eventType === "value" ) {
1674+ this . query . addValueEventListener ( listener as com . google . firebase . database . ValueEventListener ) ;
1675+ } else if ( eventType === "child_added" || eventType === "child_changed" || eventType === "child_removed" || eventType === "child_moved" ) {
1676+ this . query . addChildEventListener ( listener as com . google . firebase . database . ChildEventListener ) ;
1677+ } else {
1678+ reject ( "Invalid eventType. Use one of the following: 'value', 'child_added', 'child_changed', 'child_removed', or 'child_moved'" ) ;
1679+ return ;
1680+ }
1681+ // Add listener to our map which keeps track of eventType: child/value events
1682+ if ( ! Query . eventListenerMap . has ( eventType ) ) {
1683+ Query . eventListenerMap . set ( eventType , [ ] ) ;
1684+ }
1685+ Query . eventListenerMap . get ( eventType ) . push ( listener ) ; // We need to keep track of the listeners to fully remove them when calling off
1686+ resolve ( ) ;
1687+ } catch ( ex ) {
1688+ console . log ( "Error in firebase.addValueEventListener: " + ex ) ;
1689+ reject ( ex ) ;
1690+ }
1691+ } ) ;
1692+ }
1693+
1694+ once ( eventType : string ) : Promise < any > {
1695+ return new Promise ( ( resolve , reject ) => {
1696+ firebase . getValue ( this . path ) . then ( result => {
1697+ resolve ( {
1698+ key : result . key ,
1699+ val : ( ) => result . value ,
1700+ exists : ( ) => ! ! result . value
1701+ } ) ;
1702+ } ) ;
1703+ } ) ;
1704+ }
1705+
1706+ off ( eventType ?: string ) : void {
1707+ // Remove all events if none specified
1708+ if ( ! eventType ) {
1709+ Query . eventListenerMap . forEach ( ( value : any [ ] , key : string ) => {
1710+ firebase . removeEventListeners ( value , this . path ) ;
1711+ } ) ;
1712+ } else { // Remove only the event specified by the user
1713+ if ( Query . eventListenerMap . get ( eventType ) ) {
1714+ firebase . removeEventListeners ( Query . eventListenerMap . get ( eventType ) , this . path ) ;
1715+ }
1716+ }
1717+ }
1718+
1719+ orderByChild ( value : string ) : Query {
1720+ if ( this . query ) {
1721+ throw new Error ( "You can't combine multiple orderBy calls!" ) ;
1722+ }
1723+ this . query = this . dbRef . orderByChild ( value ) ;
1724+ return this ;
1725+ }
1726+
1727+ orderByKey ( ) : Query {
1728+ if ( this . query ) {
1729+ throw new Error ( "You can't combine multiple orderBy calls!" ) ;
1730+ }
1731+ this . query = this . dbRef . orderByKey ( ) ;
1732+ return this ;
1733+ }
1734+
1735+ orderByPriority ( ) : Query {
1736+ if ( this . query ) {
1737+ throw new Error ( "You can't combine multiple orderBy calls!" ) ;
1738+ }
1739+ this . query = this . dbRef . orderByPriority ( ) ;
1740+ return this ;
1741+ }
1742+
1743+ orderByValue ( ) : Query {
1744+ if ( this . query ) {
1745+ throw new Error ( "You can't combine multiple orderBy calls!" ) ;
1746+ }
1747+ this . query = this . dbRef . orderByValue ( ) ;
1748+ return this ;
1749+ }
1750+
1751+ // Unlike the order-by methods, you can combine multiple limit or range functions.
1752+ // For example, you can combine the startAt() and endAt() methods to limit the results to a specified range of values.
1753+
1754+ equalTo ( value : any , key ?: string ) : Query {
1755+ if ( key ) {
1756+ this . query = this . query . equalTo ( value , key ) ;
1757+ } else {
1758+ this . query = this . query . equalTo ( value ) ;
1759+ }
1760+ return this ;
1761+ }
1762+
1763+ startAt ( value : any , key ?: string ) : Query {
1764+ if ( key ) {
1765+ this . query = this . query . startAt ( value , key ) ;
1766+ } else {
1767+ this . query = this . query . startAt ( value ) ;
1768+ }
1769+ return this ;
1770+ }
1771+
1772+ endAt ( value : any , key ?: string ) : Query {
1773+ if ( key ) {
1774+ this . query = this . query . endAt ( value , key ) ;
1775+ } else {
1776+ this . query = this . query . endAt ( value ) ;
1777+ }
1778+ return this ;
1779+ }
1780+
1781+ limitToFirst ( value : number ) : Query {
1782+ this . query = this . query . limitToFirst ( value ) ;
1783+ return this ;
1784+ }
1785+
1786+ limitToLast ( value : number ) : Query {
1787+ this . query = this . query . limitToLast ( value ) ;
1788+ return this ;
1789+ }
1790+ /**
1791+ * Depending on the eventType, attach listeners at the specified Database location. Follow the WebApi which listens
1792+ * to specific events (Android is more generic value / child - which includes all events add, change, remove etc).
1793+ * Similar to firebase._addObserver but I do not want to listen for every event
1794+ */
1795+ private createEventListener ( eventType : string , callback ) : com . google . firebase . database . ValueEventListener | com . google . firebase . database . ChildEventListener {
1796+ let listener ;
1797+
1798+ if ( eventType === "value" ) {
1799+ listener = new com . google . firebase . database . ValueEventListener ( {
1800+ onDataChange : ( snapshot : com . google . firebase . database . DataSnapshot ) => {
1801+ callback ( firebase . getCallbackData ( 'ValueChanged' , snapshot ) ) ;
1802+ } ,
1803+ onCancelled : ( databaseError : com . google . firebase . database . DatabaseError ) => {
1804+ callback ( {
1805+ error : databaseError . getMessage ( )
1806+ } ) ;
1807+ }
1808+ } ) ;
1809+ } else if ( eventType === "child_added" || eventType === "child_changed" || eventType === "child_removed" || eventType === "child_moved" ) {
1810+ listener = new com . google . firebase . database . ChildEventListener ( {
1811+ onCancelled : ( databaseError : com . google . firebase . database . DatabaseError ) => {
1812+ callback ( {
1813+ error : databaseError . getMessage ( )
1814+ } ) ;
1815+ } ,
1816+ onChildAdded : ( snapshot : com . google . firebase . database . DataSnapshot , previousChildKey : string ) => {
1817+ if ( eventType === "child_added" ) {
1818+ callback ( firebase . getCallbackData ( eventType , snapshot ) ) ;
1819+ }
1820+ } ,
1821+ onChildRemoved : ( snapshot : com . google . firebase . database . DataSnapshot ) => {
1822+ if ( eventType === "child_removed" ) {
1823+ callback ( firebase . getCallbackData ( eventType , snapshot ) ) ;
1824+ }
1825+ } ,
1826+ onChildChanged : ( snapshot : com . google . firebase . database . DataSnapshot , previousChildKey : string ) => {
1827+ if ( eventType === "child_changed" ) {
1828+ callback ( firebase . getCallbackData ( eventType , snapshot ) ) ;
1829+ }
1830+ } ,
1831+ onChildMoved : ( snapshot : com . google . firebase . database . DataSnapshot , previousChildKey : string ) => {
1832+ if ( eventType === "child_moved" ) {
1833+ callback ( firebase . getCallbackData ( eventType , snapshot ) ) ;
1834+ }
1835+ }
1836+ } ) ;
1837+ }
1838+ return listener ;
1839+ }
1840+ }
1841+
1842+ firebase . query = ( updateCallback , path , options ) => {
1843+ return new Promise ( ( resolve , reject ) => {
1844+ > >>> >>> [ query ] - Rework firebaseWebApi queries to allow chaining of filters . Android implementation
16271845 try {
16281846 if ( firebase . instance === null ) {
16291847 reject ( "Run init() first!" ) ;
0 commit comments